Micron Document
C.S.Burner 🪙 ━►🔥GIT Node


Displaying Raw • Download

meshchatx/src/frontend/components/App.vue 291f06de3bff08b88560919cda3618b3eee2f08e (291f06de) Text, 114.22 KB

Tff7b72<!Tff7b72-Tff7b72- Te6edf3SPDXTff7b72-Te6edf3LicenseTff7b72-Te6edf3IdentifierTb4b4b4: T79c0ff0Te6edf3BSD Tff7b72AND Te6edf3MIT Tff7b72-Tff7b72-Tff7b72>

Tff7b72<Te6edf3templateTff7b72>
Tff7b72<Te6edf3div
:Tff7b72classTff7b72=Ta5d6ff"{ dark: config?.theme === 'dark' }"
Tff7b72classTff7b72=Ta5d6ff"h-dvh min-h-0 w-full flex flex-col transition-colors"
:Te6edf3styleTff7b72=Ta5d6ff"shellCanvasStyle"
Tff7b72>
Tff7b72<Te6edf3AppShellBanners
:Te6edf3showTff7b72-Te6edf3emergencyTff7b72=Ta5d6ff"Boolean(appInfo?.emergency)"
:Te6edf3emergencyTff7b72-Te6edf3labelTff7b72=Ta5d6ff"$t('app.emergency_mode_active')"
:Te6edf3showTff7b72-Te6edf3wsTff7b72-Te6edf3disconnectedTff7b72=Ta5d6ff"showWsDisconnectedBanner"
:Te6edf3wsTff7b72-Te6edf3disconnectedTff7b72-Te6edf3labelTff7b72=Ta5d6ff"backendOfflineBannerLabel"
:Te6edf3showTff7b72-Te6edf3backendTff7b72-Te6edf3recoveryTff7b72-Te6edf3actionsTff7b72=Ta5d6ff"showBackendRecoveryActions"
:Te6edf3backendTff7b72-Te6edf3restartingTff7b72=Ta5d6ff"backendRestarting"
:Te6edf3restartTff7b72-Te6edf3backendTff7b72-Te6edf3labelTff7b72=Ta5d6ff"$t('app.restart_backend')"
:Tff7b72viewTff7b72-Te6edf3backendTff7b72-Te6edf3logsTff7b72-Te6edf3labelTff7b72=Ta5d6ff"$t('app.view_backend_logs')"
:Te6edf3showTff7b72-Te6edf3wsTff7b72-Te6edf3reconnectedTff7b72=Ta5d6ff"wsReconnectedBanner"
:Te6edf3wsTff7b72-Te6edf3reconnectedTff7b72-Te6edf3labelTff7b72=Ta5d6ff"$t('app.backend_reconnected')"
:Te6edf3showTff7b72-Te6edf3networkTff7b72-Te6edf3degradedTff7b72=Ta5d6ff"showNetworkDegradedBanner"
:Te6edf3networkTff7b72-Te6edf3degradedTff7b72-Te6edf3labelTff7b72=Ta5d6ff"networkDegradedBannerLabel"
:Te6edf3networkTff7b72-Te6edf3recoveringTff7b72=Ta5d6ff"networkRecovering"
:Te6edf3recoverTff7b72-Te6edf3networkTff7b72-Te6edf3labelTff7b72=Ta5d6ff"$t('app.recover_network')"
:Tff7b72openTff7b72-Te6edf3interfacesTff7b72-Te6edf3labelTff7b72=Ta5d6ff"$t('app.open_interfaces')"
Te6edf3@restartTff7b72-Te6edf3backendTff7b72=Ta5d6ff"onRestartBackend"
Te6edf3@viewTff7b72-Te6edf3backendTff7b72-Te6edf3logsTff7b72=Ta5d6ff"onViewBackendCrashReport"
Te6edf3@recoverTff7b72-Te6edf3networkTff7b72=Ta5d6ff"onRecoverNetwork"
Te6edf3@openTff7b72-Te6edf3interfacesTff7b72=Ta5d6ff"onOpenInterfacesForRecovery"
Tff7b72/Tff7b72>

Tff7b72<Te6edf3RouterView Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"$route.name === 'auth'" Tff7b72/Tff7b72>

Tff7b72<Te6edf3template Te6edf3vTff7b72-Tff7b72elseTff7b72>
Tff7b72<Te6edf3div
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"isPopoutMode"
Tff7b72classTff7b72=Ta5d6ff"flex flex-1 h-full w-full overflow-hidden transition-colors"
:Te6edf3styleTff7b72=Ta5d6ff"shellCanvasStyle"
Tff7b72>
Tff7b72<Te6edf3RouterView Tff7b72classTff7b72=Ta5d6ff"flex-1" Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>

Tff7b72<Te6edf3template Te6edf3vTff7b72-Tff7b72elseTff7b72>
Tff7b72<Te6edf3div
Tff7b72classTff7b72=Ta5d6ff"z-100 flex shrink-0 bg-white dark:bg-zinc-950 border-gray-200 dark:border-zinc-800 border-b min-h-16 shadow-xs transition-colors pt-[env(safe-area-inset-top,0px)]"
Tff7b72>
Tff7b72<Te6edf3div
Tff7b72classTff7b72=Ta5d6ff"flex w-full min-h-16 items-center gap-0 overflow-x-auto no-scrollbar pl-2 pr-2 sm:ps-0 sm:pe-4"
Tff7b72>
Tff7b72<Te6edf3button
Te6edf3typeTff7b72=Ta5d6ff"button"
Tff7b72classTff7b72=Ta5d6ff"sm:hidden shrink-0 mr-2 inline-flex min-h-[44px] min-w-[44px] items-center justify-center text-gray-500 hover:text-gray-600 dark:text-gray-400 dark:hover:text-gray-300"
Te6edf3@clickTff7b72=Ta5d6ff"isSidebarOpen = !isSidebarOpen"
Tff7b72>
Tff7b72<Te6edf3MaterialDesignIcon :Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"isSidebarOpen ? 'close' : 'menu'" Tff7b72classTff7b72=Ta5d6ff"size-6" Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"flex min-w-0 flex-1 items-center gap-2 sm:flex-initial sm:gap-3"Tff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"hidden shrink-0 justify-start sm:flex sm:w-16 sm:justify-center"Tff7b72>
Tff7b72<Te6edf3div
Tff7b72classTff7b72=Ta5d6ff"flex h-10 w-10 cursor-pointer items-center justify-center overflow-hidden rounded-xl sm:h-14 sm:w-14"
Te6edf3@clickTff7b72=Ta5d6ff"onAppNameClick"
Tff7b72>
Tff7b72<Te6edf3img
Tff7b72classTff7b72=Ta5d6ff"h-9 w-9 max-h-full max-w-full object-contain sm:h-[3.25rem] sm:w-[3.25rem]"
:Te6edf3srcTff7b72=Ta5d6ff"logoUrl"
Te6edf3altTff7b72=Ta5d6ff""
Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"hidden min-w-0 leading-tight sm:block"Tff7b72>
Tff7b72<Te6edf3div
Tff7b72classTff7b72=Ta5d6ff"font-semibold cursor-pointer text-gray-900 dark:text-zinc-100 hover:text-blue-600 dark:hover:text-blue-400 transition-colors tracking-tight text-lg"
Te6edf3@clickTff7b72=Ta5d6ff"onAppNameClick"
Tff7b72>
{{ $Te6edf3tTb4b4b4(Ta5d6ff"app.name"Tb4b4b4) }}
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"text-sm text-gray-600 dark:text-zinc-300"Tff7b72>
{{ $Te6edf3tTb4b4b4(Ta5d6ff"app.tagline"Tb4b4b4) }}
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"flex ml-auto shrink-0 items-center mr-0 sm:mr-2 space-x-1 sm:space-x-2"Tff7b72>
Tff7b72<Te6edf3button
Te6edf3typeTff7b72=Ta5d6ff"button"
Tff7b72classTff7b72=Ta5d6ff"relative hidden sm:inline-flex rounded-full p-1.5 sm:p-2 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-zinc-800 transition-colors"
:Te6edf3titleTff7b72=Ta5d6ff"config?.theme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'"
Te6edf3@clickTff7b72=Ta5d6ff"toggleTheme"
Tff7b72>
Tff7b72<Te6edf3MaterialDesignIcon
:Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"config?.theme === 'dark' ? 'brightness-6' : 'brightness-4'"
Tff7b72classTff7b72=Ta5d6ff"w-5 h-5 sm:w-6 sm:h-6"
Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Te6edf3LanguageSelector Tff7b72classTff7b72=Ta5d6ff"hidden sm:block" Te6edf3@languageTff7b72-Te6edf3changeTff7b72=Ta5d6ff"onLanguageChange" Tff7b72/Tff7b72>
Tff7b72<Te6edf3button
Te6edf3typeTff7b72=Ta5d6ff"button"
Tff7b72classTff7b72=Ta5d6ff"sm:hidden rounded-full p-2 min-h-[44px] min-w-[44px] inline-flex items-center justify-center text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-zinc-800 transition-colors relative"
:Te6edf3titleTff7b72=Ta5d6ff"$t('app.messages')"
Te6edf3@clickTff7b72=Ta5d6ff"$router.push({ name: 'messages' })"
Tff7b72>
Tff7b72<Te6edf3MaterialDesignIcon Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"message-text" Tff7b72classTff7b72=Ta5d6ff"w-5 h-5" Tff7b72/Tff7b72>
Tff7b72<Te6edf3span
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"unreadConversationsCount > 0"
Tff7b72classTff7b72=Ta5d6ff"absolute -top-0.5 -right-0.5 inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-bold leading-none text-white"
Tff7b72>
{{ Te6edf3unreadConversationsCount Tff7b72> T79c0ff99 Tff7b72? Ta5d6ff"99+" : Te6edf3unreadConversationsCount }}
Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Te6edf3button
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"rrcEnabled"
Te6edf3typeTff7b72=Ta5d6ff"button"
Tff7b72classTff7b72=Ta5d6ff"relative sm:hidden rounded-full p-2 min-h-[44px] min-w-[44px] inline-flex items-center justify-center text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-zinc-800 transition-colors"
:Te6edf3titleTff7b72=Ta5d6ff"$t('app.relay_chat')"
Te6edf3@clickTff7b72=Ta5d6ff"$router.push({ name: 'relay-chat' })"
Tff7b72>
Tff7b72<Te6edf3MaterialDesignIcon Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"forum" Tff7b72classTff7b72=Ta5d6ff"w-5 h-5" Tff7b72/Tff7b72>
Tff7b72<Te6edf3span
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"relayChatUnreadCount > 0"
Tff7b72classTff7b72=Ta5d6ff"absolute -top-0.5 -right-0.5 inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-bold leading-none text-white"
Tff7b72>
{{ Te6edf3relayChatUnreadCount Tff7b72> T79c0ff99 Tff7b72? Ta5d6ff"99+" : Te6edf3relayChatUnreadCount }}
Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Te6edf3button
Te6edf3typeTff7b72=Ta5d6ff"button"
Tff7b72classTff7b72=Ta5d6ff"relative rounded-full p-2 min-h-[44px] min-w-[44px] inline-flex items-center justify-center sm:p-2 sm:min-h-0 sm:min-w-0 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-zinc-800 transition-colors"
:Te6edf3titleTff7b72=Ta5d6ff"$t('app.audio_calls')"
Te6edf3@clickTff7b72=Ta5d6ff"$router.push({ name: 'call' })"
Tff7b72>
Tff7b72<Te6edf3MaterialDesignIcon Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"phone" Tff7b72classTff7b72=Ta5d6ff"w-5 h-5 sm:w-6 sm:h-6" Tff7b72/Tff7b72>
Tff7b72<Te6edf3span
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"missedCallsCount > 0"
Tff7b72classTff7b72=Ta5d6ff"absolute -top-0.5 -right-0.5 inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-bold leading-none text-white"
Tff7b72>
{{ Te6edf3missedCallsCount Tff7b72> T79c0ff99 Tff7b72? Ta5d6ff"99+" : Te6edf3missedCallsCount }}
Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Te6edf3button
Te6edf3typeTff7b72=Ta5d6ff"button"
Tff7b72classTff7b72=Ta5d6ff"sm:hidden rounded-full p-2 min-h-[44px] min-w-[44px] inline-flex items-center justify-center text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-zinc-800 transition-colors"
:Te6edf3titleTff7b72=Ta5d6ff"isSyncingPropagationNode ? $t('app.syncing') : $t('app.sync_messages')"
Te6edf3@clickTff7b72=Ta5d6ff"syncPropagationNode"
Tff7b72>
Tff7b72<Te6edf3MaterialDesignIcon
Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"refresh"
Tff7b72classTff7b72=Ta5d6ff"w-5 h-5"
:Tff7b72classTff7b72=Ta5d6ff"{ 'animate-spin': isSyncingPropagationNode }"
Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Te6edf3button Te6edf3typeTff7b72=Ta5d6ff"button" Tff7b72classTff7b72=Ta5d6ff"hidden sm:flex rounded-full" Te6edf3@clickTff7b72=Ta5d6ff"syncPropagationNode"Tff7b72>
Tff7b72<Te6edf3span
Tff7b72classTff7b72=Ta5d6ff"flex text-gray-800 dark:text-zinc-100 bg-white dark:bg-zinc-800/80 border border-gray-200 dark:border-zinc-700 hover:border-blue-400 dark:hover:border-blue-400/60 px-3 py-1.5 rounded-full shadow-xs transition"
Tff7b72>
Tff7b72<Te6edf3MaterialDesignIcon
Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"refresh"
Tff7b72classTff7b72=Ta5d6ff"size-6"
:Tff7b72classTff7b72=Ta5d6ff"{ 'animate-spin': isSyncingPropagationNode }"
Tff7b72/Tff7b72>
Tff7b72<Te6edf3span Tff7b72classTff7b72=Ta5d6ff"hidden sm:inline-block my-auto mx-1 text-sm font-medium"Tff7b72>{{
Te6edf3isSyncingPropagationNode Tff7b72? $Te6edf3tTb4b4b4(Ta5d6ff"app.syncing"Tb4b4b4) : $Te6edf3tTb4b4b4(Ta5d6ff"app.sync_messages"Tb4b4b4)
}}Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Te6edf3button Te6edf3typeTff7b72=Ta5d6ff"button" Tff7b72classTff7b72=Ta5d6ff"hidden sm:flex rounded-full" Te6edf3@clickTff7b72=Ta5d6ff"composeNewMessage"Tff7b72>
Tff7b72<Te6edf3span
Tff7b72classTff7b72=Ta5d6ff"flex rounded-full border border-zinc-800 bg-zinc-900 px-3 py-1.5 text-white shadow-xs transition hover:bg-zinc-800 dark:border-zinc-400 dark:bg-zinc-200 dark:text-zinc-900 dark:hover:bg-white"
Tff7b72>
Tff7b72<Te6edf3spanTff7b72>
Tff7b72<Te6edf3MaterialDesignIcon Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"email" Tff7b72classTff7b72=Ta5d6ff"w-6 h-6" Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Te6edf3span Tff7b72classTff7b72=Ta5d6ff"hidden sm:inline-block my-auto mx-1 text-sm font-semibold"Tff7b72>{{
$Te6edf3tTb4b4b4(Ta5d6ff"app.compose"Tb4b4b4)
}}Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>

Tff7b72<!Tff7b72-Tff7b72- Te6edf3middle Tff7b72-Tff7b72-Tff7b72>
Tff7b72<Te6edf3div
Tff7b72refTff7b72=Ta5d6ff"middle"
Tff7b72classTff7b72=Ta5d6ff"relative flex flex-1 w-full overflow-hidden transition-colors"
:Te6edf3styleTff7b72=Ta5d6ff"shellCanvasStyle"
Tff7b72>
Tff7b72<!Tff7b72-Tff7b72- Te6edf3sidebar Te6edf3backdrop Tff7b72for Te6edf3mobile Tff7b72-Tff7b72-Tff7b72>
Tff7b72<Te6edf3div
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"isSidebarOpen"
Tff7b72classTff7b72=Ta5d6ff"absolute inset-0 z-65 bg-black/20 backdrop-blur-xs sm:hidden"
Te6edf3@clickTff7b72=Ta5d6ff"isSidebarOpen = false"
Tff7b72>Tff7b72<Tff7b72/Te6edf3divTff7b72>

Tff7b72<!Tff7b72-Tff7b72- Te6edf3sidebar Tff7b72-Tff7b72-Tff7b72>
Tff7b72<Te6edf3div
Tff7b72classTff7b72=Ta5d6ff"absolute inset-y-0 left-0 z-70 transform transition-all duration-300 ease-in-out sm:relative sm:inset-auto sm:z-0 sm:flex sm:translate-x-0"
:Tff7b72classTff7b72=Ta5d6ff"[
isSidebarOpen ? 'translate-x-0' : '-translate-x-full',
isSidebarCollapsed ? 'w-16' : 'w-80 md:max-lg:w-64 lg:w-80',
]"
Tff7b72>
Tff7b72<Te6edf3div
Tff7b72classTff7b72=Ta5d6ff"flex h-full w-full flex-col overflow-y-auto border-r border-gray-200 bg-white dark:border-zinc-800 dark:bg-zinc-950"
Tff7b72>
Tff7b72<!Tff7b72-Tff7b72- Te6edf3toggle Te6edf3button Tff7b72for Te6edf3desktop Tb4b4b4(Te6edf3hTff7b72-T79c0ff10 Te6edf3aligns Tff7b72with Te6edf3MessagesTff7b72/Te6edf3Nomad Te6edf3collapse Tff7b72rowsTb4b4b4) Tff7b72-Tff7b72-Tff7b72>
Tff7b72<Te6edf3div
Tff7b72classTff7b72=Ta5d6ff"hidden sm:flex h-10 shrink-0 items-center justify-end border-b border-gray-200 dark:border-zinc-800 px-2"
Tff7b72>
Tff7b72<Te6edf3button
Te6edf3typeTff7b72=Ta5d6ff"button"
Tff7b72classTff7b72=Ta5d6ff"p-1.5 rounded-lg text-gray-500 hover:bg-gray-100 dark:text-zinc-400 dark:hover:bg-zinc-800 transition-colors"
Te6edf3@clickTff7b72=Ta5d6ff"isSidebarCollapsed = !isSidebarCollapsed"
Tff7b72>
Tff7b72<Te6edf3MaterialDesignIcon
:Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"isSidebarCollapsed ? 'chevron-right' : 'chevron-left'"
Tff7b72classTff7b72=Ta5d6ff"size-5"
Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>

Tff7b72<!Tff7b72-Tff7b72- Te6edf3mobileTff7b72-Tff7b72only Te6edf3quick Te6edf3settings Tff7b72row Tb4b4b4(Te6edf3theme Tff7b72+ Tff7b72languageTb4b4b4) Tff7b72-Tff7b72-Tff7b72>
Tff7b72<Te6edf3div
Tff7b72classTff7b72=Ta5d6ff"sm:hidden flex items-center justify-between gap-2 px-3 py-2 border-b border-gray-200 dark:border-zinc-800"
Tff7b72>
Tff7b72<Te6edf3button
Te6edf3typeTff7b72=Ta5d6ff"button"
Tff7b72classTff7b72=Ta5d6ff"flex items-center gap-2 flex-1 rounded-lg px-2 py-1.5 text-sm font-medium text-gray-700 dark:text-zinc-200 hover:bg-gray-100 dark:hover:bg-zinc-800 transition-colors"
:Te6edf3titleTff7b72=Ta5d6ff"config?.theme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'"
Te6edf3@clickTff7b72=Ta5d6ff"toggleTheme"
Tff7b72>
Tff7b72<Te6edf3MaterialDesignIcon
:Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"config?.theme === 'dark' ? 'brightness-6' : 'brightness-4'"
Tff7b72classTff7b72=Ta5d6ff"w-5 h-5 shrink-0"
Tff7b72/Tff7b72>
Tff7b72<Te6edf3span Tff7b72classTff7b72=Ta5d6ff"truncate"Tff7b72>{{
Te6edf3configTff7b72?Tb4b4b4.Te6edf3theme Tff7b72=Tff7b72=Tff7b72= Ta5d6ff"dark" Tff7b72? $Te6edf3tTb4b4b4(Ta5d6ff"app.light_theme"Tb4b4b4) : $Te6edf3tTb4b4b4(Ta5d6ff"app.dark_theme"Tb4b4b4)
}}Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Te6edf3LanguageSelector Te6edf3@languageTff7b72-Te6edf3changeTff7b72=Ta5d6ff"onLanguageChange" Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>

Tff7b72<!Tff7b72-Tff7b72- Te6edf3navigation Tff7b72-Tff7b72-Tff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"flex-1"Tff7b72>
Tff7b72<Te6edf3ul Tff7b72classTff7b72=Ta5d6ff"py-3 pr-2 space-y-1"Tff7b72>
Tff7b72<Te6edf3li Te6edf3vTff7b72-Tff7b72forTff7b72=Ta5d6ff"item in visibleNavItems" :Tff7b72keyTff7b72=Ta5d6ff"item.id"Tff7b72>
Tff7b72<Te6edf3SidebarLink :Tff7b72toTff7b72=Ta5d6ff"item.route" :Tff7b72isTff7b72-Te6edf3collapsedTff7b72=Ta5d6ff"isSidebarCollapsed"Tff7b72>
Tff7b72<Te6edf3template Te6edf3#iconTff7b72>
Tff7b72<Te6edf3span Tff7b72classTff7b72=Ta5d6ff"relative inline-flex shrink-0"Tff7b72>
Tff7b72<Te6edf3MaterialDesignIcon
:Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"item.icon"
Tff7b72classTff7b72=Ta5d6ff"w-6 h-6 text-gray-700 dark:text-white"
Tff7b72/Tff7b72>
Tff7b72<Te6edf3span
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"
isSidebarCollapsed &&
getNavBadgeCount(item) > 0 &&
item.badge?.pill
"
Tff7b72classTff7b72=Ta5d6ff"absolute -right-2 -top-2 inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-bold leading-none text-white"
Tff7b72>
{{ Te6edf3formatNavBadgeCountTb4b4b4(Te6edf3itemTb4b4b4) }}
Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Tff7b72/Te6edf3templateTff7b72>
Tff7b72<Te6edf3template Te6edf3#textTff7b72>
Tff7b72<Te6edf3spanTff7b72>{{ Te6edf3itemTb4b4b4.Te6edf3label Tff7b72|Tff7b72| $Te6edf3tTb4b4b4(Te6edf3itemTb4b4b4.Te6edf3labelKeyTb4b4b4) }}Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Te6edf3span
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"getNavBadgeCount(item) > 0 && !item.badge?.pill"
Tff7b72classTff7b72=Ta5d6ff"ml-auto mr-2"
Tff7b72>
{{ Te6edf3getNavBadgeCountTb4b4b4(Te6edf3itemTb4b4b4) }}
Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Te6edf3span
Te6edf3vTff7b72-Tff7b72elseTff7b72-Tff7b72ifTff7b72=Ta5d6ff"
!isSidebarCollapsed &&
getNavBadgeCount(item) > 0 &&
item.badge?.pill
"
Tff7b72classTff7b72=Ta5d6ff"ml-auto mr-2 inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-bold leading-none text-white"
Tff7b72>
{{ Te6edf3formatNavBadgeCountTb4b4b4(Te6edf3itemTb4b4b4) }}
Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Tff7b72/Te6edf3templateTff7b72>
Tff7b72<Tff7b72/Te6edf3SidebarLinkTff7b72>
Tff7b72<Tff7b72/Te6edf3liTff7b72>
Tff7b72<Tff7b72/Te6edf3ulTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>

Tff7b72<Te6edf3divTff7b72>
Tff7b72<!Tff7b72-Tff7b72- Te6edf3my Tff7b72identity Tff7b72-Tff7b72-Tff7b72>
Tff7b72<Te6edf3div
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"config"
Tff7b72classTff7b72=Ta5d6ff"bg-white border-t border-gray-200 dark:border-zinc-800 dark:bg-zinc-950"
Tff7b72>
Tff7b72<Te6edf3div
Tff7b72classTff7b72=Ta5d6ff"flex text-gray-700 p-3 cursor-pointer"
Te6edf3@clickTff7b72=Ta5d6ff"isShowingMyIdentitySection = !isShowingMyIdentitySection"
Tff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"my-auto mr-2 shrink-0"Tff7b72>
Tff7b72<Te6edf3RouterLink :Tff7b72toTff7b72=Ta5d6ff"{ name: 'profile.icon' }" Te6edf3@clickTb4b4b4.Te6edf3stopTff7b72>
Tff7b72<Te6edf3LxmfUserIcon
:Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"config?.lxmf_user_icon_name"
:Te6edf3iconTff7b72-Te6edf3foregroundTff7b72-Te6edf3colourTff7b72=Ta5d6ff"config?.lxmf_user_icon_foreground_colour"
:Te6edf3iconTff7b72-Te6edf3backgroundTff7b72-Te6edf3colourTff7b72=Ta5d6ff"config?.lxmf_user_icon_background_colour"
Te6edf3iconTff7b72-Tff7b72classTff7b72=Ta5d6ff"size-7"
Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3RouterLinkTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"!isSidebarCollapsed"
Tff7b72classTff7b72=Ta5d6ff"my-auto min-w-0 flex-1 dark:text-white truncate"
:Te6edf3titleTff7b72=Ta5d6ff"identitySidebarLabel"
Tff7b72>
{{ Te6edf3identitySidebarLabel }}
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"!isSidebarCollapsed" Tff7b72classTff7b72=Ta5d6ff"my-auto ml-auto shrink-0"Tff7b72>
Tff7b72<Te6edf3button
Te6edf3typeTff7b72=Ta5d6ff"button"
Tff7b72classTff7b72=Ta5d6ff"my-auto inline-flex items-center gap-x-1 rounded-md bg-gray-500 px-2 py-1 text-sm font-semibold text-white shadow-xs hover:bg-gray-400 focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-500 dark:bg-zinc-800 dark:text-zinc-100 dark:hover:bg-zinc-700 dark:focus-visible:outline-zinc-500"
Te6edf3@clickTb4b4b4.Te6edf3stopTff7b72=Ta5d6ff"saveIdentitySettings"
Tff7b72>
{{ $Te6edf3tTb4b4b4(Ta5d6ff"common.save"Tb4b4b4) }}
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"isShowingMyIdentitySection && !isSidebarCollapsed"
Tff7b72classTff7b72=Ta5d6ff"divide-y divide-gray-200 text-gray-900 border-t border-gray-200 dark:divide-zinc-800 dark:text-zinc-200 dark:border-zinc-800"
Tff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"p-2"Tff7b72>
Tff7b72<Tff7b72input
Te6edf3vTff7b72-Te6edf3modelTff7b72=Ta5d6ff"displayName"
Te6edf3typeTff7b72=Ta5d6ff"text"
:Te6edf3placeholderTff7b72=Ta5d6ff"$t('app.display_name_placeholder')"
Tff7b72classTff7b72=Ta5d6ff"bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-zinc-800 dark:border-zinc-600 dark:text-zinc-200 dark:focus:ring-blue-400 dark:focus:border-blue-400"
Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"p-2 dark:border-zinc-900 overflow-hidden text-xs"Tff7b72>
Tff7b72<Te6edf3divTff7b72>{{ $Te6edf3tTb4b4b4(Ta5d6ff"app.identity_hash"Tb4b4b4) }}Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div
Tff7b72classTff7b72=Ta5d6ff"text-[10px] text-gray-700 dark:text-zinc-400 truncate font-mono cursor-pointer"
:Te6edf3titleTff7b72=Ta5d6ff"config.identity_hash"
Te6edf3@clickTff7b72=Ta5d6ff"copyValue(config.identity_hash, $t('app.identity_hash'))"
Tff7b72>
{{ Te6edf3configTb4b4b4.Te6edf3identity_hash }}
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"p-2 dark:border-zinc-900 overflow-hidden text-xs"Tff7b72>
Tff7b72<Te6edf3divTff7b72>{{ $Te6edf3tTb4b4b4(Ta5d6ff"app.lxmf_address"Tb4b4b4) }}Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"flex min-w-0 items-center gap-1"Tff7b72>
Tff7b72<Te6edf3div
Tff7b72classTff7b72=Ta5d6ff"min-w-0 flex-1 text-[10px] text-gray-700 dark:text-zinc-400 truncate font-mono cursor-pointer"
:Te6edf3titleTff7b72=Ta5d6ff"config.lxmf_address_hash"
Te6edf3@clickTff7b72=Ta5d6ff"copyValue(config.lxmf_address_hash, $t('app.lxmf_address'))"
Tff7b72>
{{ Te6edf3configTb4b4b4.Te6edf3lxmf_address_hash }}
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3button
Te6edf3typeTff7b72=Ta5d6ff"button"
Tff7b72classTff7b72=Ta5d6ff"shrink-0 rounded-lg p-1 text-gray-500 hover:text-blue-500 dark:hover:text-blue-400 transition-colors"
:Te6edf3titleTff7b72=Ta5d6ff"$t('app.show_qr')"
Te6edf3@clickTb4b4b4.Te6edf3stopTff7b72=Ta5d6ff"openLxmfQr"
Tff7b72>
Tff7b72<Te6edf3MaterialDesignIcon Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"qrcode" Tff7b72classTff7b72=Ta5d6ff"size-4" Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>

Tff7b72<!Tff7b72-Tff7b72- Te6edf3auto Te6edf3announce Tff7b72-Tff7b72-Tff7b72>
Tff7b72<Te6edf3div
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"config"
Tff7b72classTff7b72=Ta5d6ff"bg-white border-t border-gray-200 dark:border-zinc-800 dark:bg-zinc-950"
Tff7b72>
Tff7b72<Te6edf3div
Tff7b72classTff7b72=Ta5d6ff"flex text-gray-700 p-3 cursor-pointer dark:text-white"
Tff7b72dataTff7b72-Te6edf3testidTff7b72=Ta5d6ff"sidebar-announce-header"
Te6edf3@clickTff7b72=Ta5d6ff"isShowingAnnounceSection = !isShowingAnnounceSection"
Tff7b72>
Tff7b72<Te6edf3button
Te6edf3typeTff7b72=Ta5d6ff"button"
Tff7b72classTff7b72=Ta5d6ff"my-auto mr-2 flex shrink-0 items-center justify-center rounded-md border-0 bg-transparent p-0 text-inherit cursor-pointer"
:Te6edf3titleTff7b72=Ta5d6ff"$t('app.announce_now')"
Tff7b72dataTff7b72-Te6edf3testidTff7b72=Ta5d6ff"sidebar-announce-radio"
Te6edf3@clickTb4b4b4.Te6edf3stopTff7b72=Ta5d6ff"sendAnnounce"
Tff7b72>
Tff7b72<Te6edf3MaterialDesignIcon Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"radio" Tff7b72classTff7b72=Ta5d6ff"size-6" Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Te6edf3div Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"!isSidebarCollapsed" Tff7b72classTff7b72=Ta5d6ff"my-auto truncate"Tff7b72>
{{ $Te6edf3tTb4b4b4(Ta5d6ff"app.announce"Tb4b4b4) }}
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"!isSidebarCollapsed" Tff7b72classTff7b72=Ta5d6ff"ml-auto shrink-0"Tff7b72>
Tff7b72<Te6edf3button
Te6edf3typeTff7b72=Ta5d6ff"button"
Tff7b72classTff7b72=Ta5d6ff"my-auto inline-flex items-center gap-x-1 rounded-md bg-gray-500 px-2 py-1 text-sm font-semibold text-white shadow-xs hover:bg-gray-400 focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-500 dark:bg-zinc-800 dark:text-white dark:hover:bg-zinc-700 dark:focus-visible:outline-zinc-500"
Te6edf3@clickTb4b4b4.Te6edf3stopTff7b72=Ta5d6ff"sendAnnounce"
Tff7b72>
{{ $Te6edf3tTb4b4b4(Ta5d6ff"app.announce_now"Tb4b4b4) }}
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"isShowingAnnounceSection && !isSidebarCollapsed"
Tff7b72classTff7b72=Ta5d6ff"divide-y divide-gray-200 text-gray-900 border-t border-gray-200 dark:divide-zinc-800 dark:text-zinc-200 dark:border-zinc-800"
Tff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"p-2 dark:border-zinc-800"Tff7b72>
Tff7b72<Tff7b72select
Te6edf3vTff7b72-Te6edf3modelTff7b72=Ta5d6ff"config.auto_announce_interval_seconds"
Tff7b72classTff7b72=Ta5d6ff"bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-zinc-800 dark:border-zinc-600 dark:text-zinc-200 dark:focus:ring-blue-400 dark:focus:border-blue-400"
Te6edf3@changeTff7b72=Ta5d6ff"onAnnounceIntervalSecondsChange"
Tff7b72>
Tff7b72<Tff7b72option Tff7b72valueTff7b72=Ta5d6ff"0"Tff7b72>{{ $Te6edf3tTb4b4b4(Ta5d6ff"app.disabled"Tb4b4b4) }}Tff7b72<Tff7b72/Tff7b72optionTff7b72>
Tff7b72<Tff7b72option Tff7b72valueTff7b72=Ta5d6ff"900"Tff7b72>Tff7b72Every T79c0ff15 Te6edf3MinutesTff7b72<Tff7b72/Tff7b72optionTff7b72>
Tff7b72<Tff7b72option Tff7b72valueTff7b72=Ta5d6ff"1800"Tff7b72>Tff7b72Every T79c0ff30 Te6edf3MinutesTff7b72<Tff7b72/Tff7b72optionTff7b72>
Tff7b72<Tff7b72option Tff7b72valueTff7b72=Ta5d6ff"3600"Tff7b72>Tff7b72Every T79c0ff1 Tff7b72HourTff7b72<Tff7b72/Tff7b72optionTff7b72>
Tff7b72<Tff7b72option Tff7b72valueTff7b72=Ta5d6ff"10800"Tff7b72>Tff7b72Every T79c0ff3 Te6edf3HoursTff7b72<Tff7b72/Tff7b72optionTff7b72>
Tff7b72<Tff7b72option Tff7b72valueTff7b72=Ta5d6ff"21600"Tff7b72>Tff7b72Every T79c0ff6 Te6edf3HoursTff7b72<Tff7b72/Tff7b72optionTff7b72>
Tff7b72<Tff7b72option Tff7b72valueTff7b72=Ta5d6ff"43200"Tff7b72>Tff7b72Every T79c0ff12 Te6edf3HoursTff7b72<Tff7b72/Tff7b72optionTff7b72>
Tff7b72<Tff7b72option Tff7b72valueTff7b72=Ta5d6ff"86400"Tff7b72>Tff7b72Every T79c0ff24 Te6edf3HoursTff7b72<Tff7b72/Tff7b72optionTff7b72>
Tff7b72<Tff7b72/Tff7b72selectTff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"text-[10px] text-gray-700 dark:text-zinc-100 mt-1"Tff7b72>
Tff7b72<Te6edf3span Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"config.last_announced_at"Tff7b72>{{
$Te6edf3tTb4b4b4(Ta5d6ff"app.last_announced"Tb4b4b4, {
T56d364time: Te6edf3formatSecondsAgoTb4b4b4(Te6edf3configTb4b4b4.Te6edf3last_announced_atTb4b4b4)Tb4b4b4,
}Tb4b4b4)
}}Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Te6edf3span Te6edf3vTff7b72-Tff7b72elseTff7b72>{{ $Te6edf3tTb4b4b4(Ta5d6ff"app.last_announced_never"Tb4b4b4) }}Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>

Tff7b72<Te6edf3div
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"appInfo?.version"
Tff7b72classTff7b72=Ta5d6ff"shrink-0 border-t border-gray-200 bg-white dark:border-zinc-800 dark:bg-zinc-950"
Tff7b72>
Tff7b72<Te6edf3RouterLink
:Tff7b72toTff7b72=Ta5d6ff"{ name: 'about' }"
Tff7b72classTff7b72=Ta5d6ff"flex items-center py-2 text-[10px] font-mono text-gray-500 transition-colors hover:text-gray-700 dark:text-zinc-500 dark:hover:text-zinc-300"
:Tff7b72classTff7b72=Ta5d6ff"isSidebarCollapsed ? 'justify-center px-0' : 'justify-start px-3'"
Tff7b72dataTff7b72-Te6edf3testidTff7b72=Ta5d6ff"sidebar-app-version"
:Te6edf3titleTff7b72=Ta5d6ff"$t('about.version', { version: appInfo.version })"
Tff7b72>
Tff7b72<Te6edf3MaterialDesignIcon
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"isSidebarCollapsed"
Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"information-outline"
Tff7b72classTff7b72=Ta5d6ff"size-4"
Tff7b72/Tff7b72>
Tff7b72<Te6edf3span Te6edf3vTff7b72-Tff7b72elseTff7b72>{{ $Te6edf3tTb4b4b4(Ta5d6ff"about.version"Tb4b4b4, { Te6edf3versionTb4b4b4: Te6edf3appInfoTb4b4b4.Te6edf3version }Tb4b4b4) }}Tff7b72<Tff7b72/Te6edf3spanTff7b72>
Tff7b72<Tff7b72/Te6edf3RouterLinkTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>

Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"flex flex-1 min-w-0 overflow-hidden"Tff7b72>
Tff7b72<Te6edf3RouterView Te6edf3vTff7b72-Te6edf3slotTff7b72=Ta5d6ff"{ Component, route }" Tff7b72classTff7b72=Ta5d6ff"flex-1 min-w-0 h-full bg-sem-canvas"Tff7b72>
Tff7b72<Te6edf3template Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"Component"Tff7b72>
Tff7b72<Te6edf3KeepAliveTff7b72>
Tff7b72<Te6edf3component
:Tff7b72isTff7b72=Ta5d6ff"Component"
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"route.meta.keepAlive"
:Tff7b72keyTff7b72=Ta5d6ff"route.name"
Tff7b72classTff7b72=Ta5d6ff"flex-1 min-w-0 h-full bg-sem-canvas"
Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3KeepAliveTff7b72>
Tff7b72<Te6edf3Transition Te6edf3nameTff7b72=Ta5d6ff"route-view-fade" Te6edf3modeTff7b72=Ta5d6ff"out-in"Tff7b72>
Tff7b72<Te6edf3component
:Tff7b72isTff7b72=Ta5d6ff"Component"
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"!route.meta.keepAlive"
:Tff7b72keyTff7b72=Ta5d6ff"route.meta.stableKey ? route.name : route.fullPath"
Tff7b72classTff7b72=Ta5d6ff"flex-1 min-w-0 h-full bg-sem-canvas"
Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3TransitionTff7b72>
Tff7b72<Tff7b72/Te6edf3templateTff7b72>
Tff7b72<Tff7b72/Te6edf3RouterViewTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3templateTff7b72>
Tff7b72<Tff7b72/Te6edf3templateTff7b72>
Tff7b72<Te6edf3CallOverlay
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"
(activeCall || isCallEnded || wasDeclined || initiationStatus) &&
!$route.meta.isPopout &&
(!['call', 'call-popout'].includes($route.name) || activeCallTab !== 'phone') &&
(!config?.desktop_open_calls_in_separate_window || !ElectronUtils.isElectron())
"
:Te6edf3activeTff7b72-Tff7b72callTff7b72=Ta5d6ff"activeCall || lastCall"
:Tff7b72isTff7b72-Te6edf3endedTff7b72=Ta5d6ff"isCallEnded"
:Te6edf3wasTff7b72-Te6edf3declinedTff7b72=Ta5d6ff"wasDeclined"
:Te6edf3voicemailTff7b72-Te6edf3statusTff7b72=Ta5d6ff"voicemailStatus"
:Te6edf3initiationTff7b72-Te6edf3statusTff7b72=Ta5d6ff"initiationStatus"
:Te6edf3initiationTff7b72-Te6edf3targetTff7b72-Te6edf3hashTff7b72=Ta5d6ff"initiationTargetHash"
:Te6edf3initiationTff7b72-Te6edf3targetTff7b72-Te6edf3nameTff7b72=Ta5d6ff"initiationTargetName"
Te6edf3@hangupTff7b72=Ta5d6ff"onOverlayHangup"
Te6edf3@toggleTff7b72-Te6edf3micTff7b72=Ta5d6ff"onToggleMic"
Te6edf3@toggleTff7b72-Te6edf3speakerTff7b72=Ta5d6ff"onToggleSpeaker"
Tff7b72/Tff7b72>
Tff7b72<Te6edf3Toast Tff7b72/Tff7b72>
Tff7b72<Te6edf3ConfirmDialog Tff7b72/Tff7b72>
Tff7b72<Te6edf3PromptDialog Tff7b72/Tff7b72>
Tff7b72<Te6edf3CommandPalette Tff7b72/Tff7b72>
Tff7b72<Te6edf3IntegrityWarningModal Tff7b72/Tff7b72>
Tff7b72<Te6edf3ChangelogModal Tff7b72refTff7b72=Ta5d6ff"changelogModal" :Te6edf3appTff7b72-Te6edf3versionTff7b72=Ta5d6ff"appInfo?.version" Tff7b72/Tff7b72>
Tff7b72<Te6edf3TutorialModal Tff7b72refTff7b72=Ta5d6ff"tutorialModal" Tff7b72/Tff7b72>
Tff7b72<Te6edf3AndroidStorageChoicePrompt
Tff7b72refTff7b72=Ta5d6ff"androidStorageUpgradePrompt"
Te6edf3variantTff7b72=Ta5d6ff"upgrade"
Te6edf3@completedTff7b72=Ta5d6ff"onAndroidStorageUpgradeCompleted"
Tff7b72/Tff7b72>
Tff7b72<Te6edf3PostInstallPromptHost Tff7b72refTff7b72=Ta5d6ff"postInstallPromptHost" Tff7b72/Tff7b72>

Tff7b72<!Tff7b72-Tff7b72- Te6edf3LXMF Te6edf3QR Te6edf3modal Tff7b72-Tff7b72-Tff7b72>
Tff7b72<Te6edf3div
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"showLxmfQr"
Tff7b72classTff7b72=Ta5d6ff"fixed inset-0 z-190 flex items-center justify-center p-4 bg-black/60 backdrop-blur-xs"
Te6edf3@clickTb4b4b4.Te6edf3selfTff7b72=Ta5d6ff"showLxmfQr = false"
Tff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"w-full max-w-sm bg-white dark:bg-zinc-900 rounded-2xl shadow-2xl overflow-hidden"Tff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"px-4 py-3 border-b border-gray-100 dark:border-zinc-800 flex items-center justify-between"Tff7b72>
Tff7b72<Te6edf3h3 Tff7b72classTff7b72=Ta5d6ff"text-sm font-semibold text-gray-900 dark:text-white"Tff7b72>Tff7b72Identity Te6edf3QR Tb4b4b4(Te6edf3LXMATb4b4b4)Tff7b72<Tff7b72/Te6edf3h3Tff7b72>
Tff7b72<Te6edf3button
Te6edf3typeTff7b72=Ta5d6ff"button"
Tff7b72classTff7b72=Ta5d6ff"text-gray-400 hover:text-gray-600 dark:hover:text-zinc-300 transition-colors"
Te6edf3@clickTff7b72=Ta5d6ff"showLxmfQr = false"
Tff7b72>
Tff7b72<Te6edf3MaterialDesignIcon Te6edf3iconTff7b72-Te6edf3nameTff7b72=Ta5d6ff"close" Tff7b72classTff7b72=Ta5d6ff"size-5" Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"p-4 space-y-3"Tff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"flex justify-center"Tff7b72>
Tff7b72<Te6edf3img
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"lxmfQrDataUrl"
:Te6edf3srcTff7b72=Ta5d6ff"lxmfQrDataUrl"
Te6edf3altTff7b72=Ta5d6ff"LXMF QR"
Tff7b72classTff7b72=Ta5d6ff"w-48 h-48 bg-white rounded-xl border border-gray-200 dark:border-zinc-800"
Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"config?.lxmf_address_hash"
Tff7b72classTff7b72=Ta5d6ff"text-xs font-mono text-gray-700 dark:text-zinc-200 text-center wrap-break-word"
Tff7b72>
{{ Te6edf3getMyIdentityUriTb4b4b4(Tb4b4b4) }}
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"flex justify-center"Tff7b72>
Tff7b72<Te6edf3button
Te6edf3typeTff7b72=Ta5d6ff"button"
Tff7b72classTff7b72=Ta5d6ff"px-3 py-1.5 text-xs font-semibold text-blue-600 dark:text-blue-400 hover:underline"
Te6edf3@clickTff7b72=Ta5d6ff"copyIdentityUri"
Tff7b72>
{{ $Te6edf3tTb4b4b4(Ta5d6ff"common.copy"Tb4b4b4) }}
Tff7b72<Tff7b72/Te6edf3buttonTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>

Tff7b72<!Tff7b72-Tff7b72- Tff7b72identity Te6edf3switching Tff7b72overlay Tff7b72-Tff7b72-Tff7b72>
Tff7b72<Te6edf3transition Te6edf3nameTff7b72=Ta5d6ff"fade-blur"Tff7b72>
Tff7b72<Te6edf3div
Te6edf3vTff7b72-Tff7b72ifTff7b72=Ta5d6ff"isSwitchingIdentity"
Tff7b72classTff7b72=Ta5d6ff"fixed inset-0 z-200 flex items-center justify-center bg-slate-900/45 dark:bg-black/55 backdrop-blur-xs px-4"
Tff7b72roleTff7b72=Ta5d6ff"status"
Te6edf3ariaTff7b72-Te6edf3liveTff7b72=Ta5d6ff"polite"
Tff7b72>
Tff7b72<Te6edf3div
Tff7b72classTff7b72=Ta5d6ff"w-full max-w-sm overflow-hidden rounded-2xl border border-gray-200/90 bg-white/95 shadow-xl dark:border-zinc-700/90 dark:bg-zinc-900/95"
Tff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"px-6 pt-7 pb-1 text-center"Tff7b72>
Tff7b72<Te6edf3div
Tff7b72classTff7b72=Ta5d6ff"mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-2xl bg-slate-50 ring-1 ring-gray-200/80 dark:bg-zinc-950 dark:ring-zinc-700"
Tff7b72>
Tff7b72<Te6edf3img :Te6edf3srcTff7b72=Ta5d6ff"logoUrl" Te6edf3altTff7b72=Ta5d6ff"" Tff7b72classTff7b72=Ta5d6ff"h-9 w-9 object-contain p-1" Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3p Tff7b72classTff7b72=Ta5d6ff"text-xs font-medium text-gray-500 dark:text-zinc-500"Tff7b72>
{{ $Te6edf3tTb4b4b4(Ta5d6ff"app.loading_overlay_kicker"Tb4b4b4) }}
Tff7b72<Tff7b72/Te6edf3pTff7b72>
Tff7b72<Te6edf3h2 Tff7b72classTff7b72=Ta5d6ff"mt-1.5 text-lg font-semibold tracking-tight text-gray-900 dark:text-white"Tff7b72>
{{ $Te6edf3tTb4b4b4(Ta5d6ff"app.loading_overlay_title"Tb4b4b4) }}
Tff7b72<Tff7b72/Te6edf3h2Tff7b72>
Tff7b72<Te6edf3p Tff7b72classTff7b72=Ta5d6ff"mt-3 text-sm leading-relaxed text-gray-600 dark:text-zinc-400"Tff7b72>
{{ $Te6edf3tTb4b4b4(Ta5d6ff"app.loading_overlay_subtitle"Tb4b4b4) }}
Tff7b72<Tff7b72/Te6edf3pTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"px-6 pb-7 pt-2"Tff7b72>
Tff7b72<Te6edf3div Tff7b72classTff7b72=Ta5d6ff"h-1 w-full overflow-hidden rounded-full bg-gray-200 dark:bg-zinc-800"Tff7b72>
Tff7b72<Te6edf3div
Tff7b72classTff7b72=Ta5d6ff"identity-switch-indeterminate h-full w-1/3 rounded-full bg-blue-600 dark:bg-blue-500"
Tff7b72/Tff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3transitionTff7b72>
Tff7b72<Tff7b72/Te6edf3divTff7b72>
Tff7b72<Tff7b72/Te6edf3templateTff7b72>

Tff7b72<Te6edf3scriptTff7b72>
Te6edf3import { Te6edf3watch } Tff7b72from Ta5d6ff"vue"Tb4b4b4;
Te6edf3import { Te6edf3useTheme } Tff7b72from Ta5d6ff"vuetify"Tb4b4b4;
Te6edf3import Te6edf3SidebarLink Tff7b72from Ta5d6ff"./SidebarLink.vue"Tb4b4b4;
Te6edf3import Te6edf3DialogUtils Tff7b72from Ta5d6ff"../js/DialogUtils"Tb4b4b4;
Te6edf3import Te6edf3WebSocketConnection Tff7b72from Ta5d6ff"../js/WebSocketConnection"Tb4b4b4;
Te6edf3import { Te6edf3formatDisconnectedDuration } Tff7b72from Ta5d6ff"../js/wsConnectionSupport"Tb4b4b4;
Te6edf3import Te6edf3GlobalStateTb4b4b4, { Te6edf3mergeGlobalConfig } Tff7b72from Ta5d6ff"../js/GlobalState"Tb4b4b4;
Te6edf3import { Te6edf3countRelayMentions } Tff7b72from Ta5d6ff"../js/relayMentionCount.js"Tb4b4b4;
Te6edf3import Te6edf3Utils Tff7b72from Ta5d6ff"../js/Utils"Tb4b4b4;
Te6edf3import Te6edf3GlobalEmitter Tff7b72from Ta5d6ff"../js/GlobalEmitter"Tb4b4b4;
Te6edf3import Te6edf3NotificationUtils Tff7b72from Ta5d6ff"../js/NotificationUtils"Tb4b4b4;
Te6edf3import Te6edf3NotificationSoundUtils Tff7b72from Ta5d6ff"../js/NotificationSoundUtils"Tb4b4b4;
Te6edf3import {
Te6edf3deliverySourceHashTb4b4b4,
Te6edf3isUserFacingLxmfDeliveryMessageTb4b4b4,
Te6edf3shouldPlayMessageSoundTb4b4b4,
Te6edf3shouldShowOsMessageNotificationTb4b4b4,
} Tff7b72from Ta5d6ff"../js/notificationPolicy.js"Tb4b4b4;
Te6edf3import { Te6edf3listOpenDestinationHashesTb4b4b4, Te6edf3subscribeOpenDestinationHashes } Tff7b72from Ta5d6ff"../js/activeConversationStore.js"Tb4b4b4;
Te6edf3import Te6edf3LxmfUserIcon Tff7b72from Ta5d6ff"./LxmfUserIcon.vue"Tb4b4b4;
Te6edf3import Te6edf3Toast Tff7b72from Ta5d6ff"./Toast.vue"Tb4b4b4;
Te6edf3import Te6edf3ConfirmDialog Tff7b72from Ta5d6ff"./ConfirmDialog.vue"Tb4b4b4;
Te6edf3import Te6edf3PromptDialog Tff7b72from Ta5d6ff"./PromptDialog.vue"Tb4b4b4;
Te6edf3import Te6edf3ToastUtils Tff7b72from Ta5d6ff"../js/ToastUtils"Tb4b4b4;
Te6edf3import {
Te6edf3CLIENT_HEAP_SAMPLE_INTERVAL_MSTb4b4b4,
Te6edf3MEMORY_WARNING_TOAST_KEYTb4b4b4,
Te6edf3evaluateClientHeapSampleTb4b4b4,
Te6edf3handleHealthWarningPayloadTb4b4b4,
Te6edf3markMemoryWarningDismissedTb4b4b4,
Te6edf3showMemoryWarningToastIfNeededTb4b4b4,
} Tff7b72from Ta5d6ff"../js/healthMemoryWarning.js"Tb4b4b4;
Te6edf3import Te6edf3MaterialDesignIcon Tff7b72from Ta5d6ff"./MaterialDesignIcon.vue"Tb4b4b4;
Te6edf3import Te6edf3QRCode Tff7b72from Ta5d6ff"qrcode"Tb4b4b4;
Te6edf3import Te6edf3LanguageSelector Tff7b72from Ta5d6ff"./LanguageSelector.vue"Tb4b4b4;
Te6edf3import Te6edf3CallOverlay Tff7b72from Ta5d6ff"./call/CallOverlay.vue"Tb4b4b4;
Te6edf3import Te6edf3CommandPalette Tff7b72from Ta5d6ff"./CommandPalette.vue"Tb4b4b4;
Te6edf3import Te6edf3IntegrityWarningModal Tff7b72from Ta5d6ff"./IntegrityWarningModal.vue"Tb4b4b4;
Te6edf3import Te6edf3ChangelogModal Tff7b72from Ta5d6ff"./ChangelogModal.vue"Tb4b4b4;
Te6edf3import Te6edf3TutorialModal Tff7b72from Ta5d6ff"./TutorialModal.vue"Tb4b4b4;
Te6edf3import Te6edf3AndroidStorageChoicePrompt Tff7b72from Ta5d6ff"./AndroidStorageChoicePrompt.vue"Tb4b4b4;
Te6edf3import Te6edf3PostInstallPromptHost Tff7b72from Ta5d6ff"./PostInstallPromptHost.vue"Tb4b4b4;
Te6edf3import Te6edf3AppShellBanners Tff7b72from Ta5d6ff"./layout/AppShellBanners.vue"Tb4b4b4;
Te6edf3import Te6edf3KeyboardShortcuts Tff7b72from Ta5d6ff"../js/KeyboardShortcuts"Tb4b4b4;
Te6edf3import Te6edf3ElectronUtils Tff7b72from Ta5d6ff"../js/ElectronUtils"Tb4b4b4;
Te6edf3import { Te6edf3postRequestPath } Tff7b72from Ta5d6ff"../js/reticulumPathfinding.js"Tb4b4b4;
Te6edf3import Te6edf3ToneGenerator Tff7b72from Ta5d6ff"../js/ToneGenerator"Tb4b4b4;
Te6edf3import { Te6edf3listNavItems } Tff7b72from Ta5d6ff"../js/registries/navRegistry.js"Tb4b4b4;
Te6edf3import { Te6edf3onWsEventTb4b4b4, Te6edf3offWsEvent } Tff7b72from Ta5d6ff"../js/registries/wsEventRegistry.js"Tb4b4b4;
Te6edf3import { Te6edf3handleLxmIngestUriResult } Tff7b72from Ta5d6ff"../js/ingestUriResultNavigation.js"Tb4b4b4;
Te6edf3import { Te6edf3applyRelayShareLinkTb4b4b4, Te6edf3parseMeshchatRelayUri } Tff7b72from Ta5d6ff"../js/relayLinkUtils.js"Tb4b4b4;
Te6edf3import Te6edf3logoUrl Tff7b72from Ta5d6ff"../assets/images/logo.png"Tb4b4b4;
Te6edf3import { Te6edf3loadFeatureSidebarCollapsedTb4b4b4, Te6edf3saveFeatureSidebarCollapsed } Tff7b72from Ta5d6ff"../js/browserLayoutStore"Tb4b4b4;
Te6edf3import {
Te6edf3applyBackgroundPollIntervalTb4b4b4,
Te6edf3BATTERY_SAVER_CHANGED_EVENTTb4b4b4,
Te6edf3loadBatterySaverPrefsTb4b4b4,
} Tff7b72from Ta5d6ff"../js/settings/batterySaverPrefs.js"Tb4b4b4;

Te6edf3export Tff7b72default {
Te6edf3nameTb4b4b4: Ta5d6ff"App"Tb4b4b4,
Te6edf3componentsTb4b4b4: {
Te6edf3LxmfUserIconTb4b4b4,
Te6edf3SidebarLinkTb4b4b4,
Te6edf3ToastTb4b4b4,
Te6edf3ConfirmDialogTb4b4b4,
Te6edf3PromptDialogTb4b4b4,
Te6edf3MaterialDesignIconTb4b4b4,
Te6edf3LanguageSelectorTb4b4b4,
Te6edf3CallOverlayTb4b4b4,
Te6edf3CommandPaletteTb4b4b4,
Te6edf3IntegrityWarningModalTb4b4b4,
Te6edf3ChangelogModalTb4b4b4,
Te6edf3TutorialModalTb4b4b4,
Te6edf3AndroidStorageChoicePromptTb4b4b4,
Te6edf3PostInstallPromptHostTb4b4b4,
Te6edf3AppShellBannersTb4b4b4,
}Tb4b4b4,
Te6edf3setupTb4b4b4(Tb4b4b4) {
Te6edf3const Te6edf3vuetifyTheme Tff7b72= Te6edf3useThemeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return {
Te6edf3vuetifyThemeTb4b4b4,
}Tb4b4b4;
}Tb4b4b4,
Tff7b72dataTb4b4b4(Tb4b4b4) {
Tff7b72return {
Te6edf3logoUrlTb4b4b4,
Te6edf3ElectronUtilsTb4b4b4,
Te6edf3reloadIntervalTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3appInfoIntervalTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3unreadCountIntervalTb4b4b4: Tff7b72nullTb4b4b4,

Te6edf3isShowingMyIdentitySectionTb4b4b4: Tff7b72trueTb4b4b4,
Te6edf3isShowingAnnounceSectionTb4b4b4: Tff7b72trueTb4b4b4,

Te6edf3isSidebarOpenTb4b4b4: Tff7b72falseTb4b4b4,
Te6edf3isSidebarCollapsedTb4b4b4: Tff7b72falseTb4b4b4,

Te6edf3isSwitchingIdentityTb4b4b4: Tff7b72falseTb4b4b4,
Te6edf3shellRunningTb4b4b4: Tff7b72falseTb4b4b4,

Te6edf3displayNameTb4b4b4: Ta5d6ff"Anonymous Peer"Tb4b4b4,
Te6edf3configTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3appInfoTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3hasCheckedForModalsTb4b4b4: Tff7b72falseTb4b4b4,

Te6edf3showLxmfQrTb4b4b4: Tff7b72falseTb4b4b4,
Te6edf3lxmfQrDataUrlTb4b4b4: Tff7b72nullTb4b4b4,

Te6edf3activeCallTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3propagationNodeStatusTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3isCallEndedTb4b4b4: Tff7b72falseTb4b4b4,
Te6edf3wasDeclinedTb4b4b4: Tff7b72falseTb4b4b4,
Te6edf3lastCallTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3voicemailStatusTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3isMicMutingTb4b4b4: Tff7b72falseTb4b4b4,
Te6edf3isSpeakerMutingTb4b4b4: Tff7b72falseTb4b4b4,
Te6edf3endedTimeoutTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3ringtonePlayerTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3ringtoneAutoplayBlockedTb4b4b4: Tff7b72falseTb4b4b4,
Te6edf3toneGeneratorTb4b4b4: Tff7b72new Te6edf3ToneGeneratorTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3isFetchingRingtoneTb4b4b4: Tff7b72falseTb4b4b4,
Te6edf3initiationStatusTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3initiationTargetHashTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3initiationTargetNameTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3isCallWindowOpenTb4b4b4: Tff7b72falseTb4b4b4,

Te6edf3wsDisconnectedTb4b4b4: Tff7b72falseTb4b4b4,
Te6edf3wsDisconnectedAtTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3wsDisconnectedDurationTextTb4b4b4: Ta5d6ff""Tb4b4b4,
Te6edf3wsReconnectedBannerTb4b4b4: Tff7b72falseTb4b4b4,
Te6edf3wsDisconnectTickTimerTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3wsReconnectedHideTimerTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3backendProcessExitedTb4b4b4: Tff7b72falseTb4b4b4,
Te6edf3backendExitCodeTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3backendRestartingTb4b4b4: Tff7b72falseTb4b4b4,
Te6edf3networkRecoveringTb4b4b4: Tff7b72falseTb4b4b4,
Te6edf3userInitiatedPropagationSyncTb4b4b4: Tff7b72falseTb4b4b4,

Te6edf3identitySwitchDedupeHashTb4b4b4: Tff7b72nullTb4b4b4,
Te6edf3identitySwitchDedupeAtTb4b4b4: T79c0ff0Tb4b4b4,
Te6edf3shellWsHandlerCleanupsTb4b4b4: []Tb4b4b4,
}Tb4b4b4;
}Tb4b4b4,
Te6edf3computedTb4b4b4: {
Te6edf3currentPopoutTypeTb4b4b4(Tb4b4b4) {
Tff7b72if Tb4b4b4(Te6edf3thisTb4b4b4.$Te6edf3routeTff7b72?Tb4b4b4.Te6edf3metaTff7b72?Tb4b4b4.Te6edf3popoutTypeTb4b4b4) {
Tff7b72return Te6edf3thisTb4b4b4.$Te6edf3routeTb4b4b4.Te6edf3metaTb4b4b4.Te6edf3popoutTypeTb4b4b4;
}
Tff7b72return Te6edf3thisTb4b4b4.$Te6edf3routeTff7b72?Tb4b4b4.Te6edf3queryTff7b72?Tb4b4b4.Te6edf3popout Tff7b72?Tff7b72? Te6edf3thisTb4b4b4.Te6edf3getHashPopoutValueTb4b4b4(Tb4b4b4)Tb4b4b4;
}Tb4b4b4,
Te6edf3isPopoutModeTb4b4b4(Tb4b4b4) {
Tff7b72return Te6edf3thisTb4b4b4.Te6edf3currentPopoutType Tff7b72!= Tff7b72nullTb4b4b4;
}Tb4b4b4,
Te6edf3unreadConversationsCountTb4b4b4(Tb4b4b4) {
Tff7b72return Te6edf3GlobalStateTb4b4b4.Te6edf3unreadConversationsCountTb4b4b4;
}Tb4b4b4,
Te6edf3relayChatUnreadCountTb4b4b4(Tb4b4b4) {
Tff7b72return Te6edf3GlobalStateTb4b4b4.Te6edf3relayChatUnreadCountTb4b4b4;
}Tb4b4b4,
Te6edf3missedCallsCountTb4b4b4(Tb4b4b4) {
Tff7b72return Te6edf3GlobalStateTb4b4b4.Te6edf3missedCallsCountTb4b4b4;
}Tb4b4b4,
Te6edf3rrcEnabledTb4b4b4(Tb4b4b4) {
Tff7b72return Te6edf3GlobalStateTb4b4b4.Te6edf3configTff7b72?Tb4b4b4.Te6edf3rrc_enabled Tff7b72!=Tff7b72= Tff7b72falseTb4b4b4;
}Tb4b4b4,
Te6edf3visibleNavItemsTb4b4b4(Tb4b4b4) {
Tff7b72return Te6edf3listNavItemsTb4b4b4(Tb4b4b4)Tb4b4b4.Tff7b72filterTb4b4b4(Tb4b4b4(Te6edf3itemTb4b4b4) Tff7b72=Tff7b72> Te6edf3thisTb4b4b4.Te6edf3isNavItemVisibleTb4b4b4(Te6edf3itemTb4b4b4)Tb4b4b4)Tb4b4b4;
}Tb4b4b4,
Te6edf3isSyncingPropagationNodeTb4b4b4(Tb4b4b4) {
Tff7b72/Tff7b72/ Tff7b72Only Tff7b72treat Te6edf3sync Tff7b72as Ta5d6ff"running" Tff7b72in Te6edf3the Te6edf3chrome Tff7b72when Te6edf3the Tff7b72user Te6edf3started Te6edf3itTb4b4b4.
Tff7b72/Tff7b72/ Te6edf3Background Te6edf3autoTff7b72-Te6edf3sync Te6edf3must Tff7b72not Te6edf3keep Te6edf3the Te6edf3header Te6edf3spinner Te6edf3foreverTb4b4b4.
Tff7b72if Tb4b4b4(!Te6edf3thisTb4b4b4.Te6edf3userInitiatedPropagationSyncTb4b4b4) {
Tff7b72return Tff7b72falseTb4b4b4;
}
Tff7b72return Tff7b72[
Te6edf3 "path_requested",
"link_establishing",
"link_established",
"request_sent",
"receiving",
"response_received",
Tff7b72]Tb4b4b4.Te6edf3includesTb4b4b4(Te6edf3thisTb4b4b4.Te6edf3propagationNodeStatusTff7b72?Tb4b4b4.Tff7b72stateTb4b4b4)Tb4b4b4;
}Tb4b4b4,
Te6edf3activeCallTabTb4b4b4(Tb4b4b4) {
Tff7b72return Te6edf3GlobalStateTb4b4b4.Te6edf3activeCallTabTb4b4b4;
}Tb4b4b4,
Te6edf3showWsDisconnectedBannerTb4b4b4(Tb4b4b4) {
Tff7b72return Te6edf3thisTb4b4b4.Te6edf3shellRunning Tff7b72&Tff7b72& Te6edf3thisTb4b4b4.Te6edf3wsDisconnected Tff7b72&Tff7b72& Te6edf3thisTb4b4b4.$Te6edf3routeTff7b72?Tb4b4b4.Te6edf3name Tff7b72!=Tff7b72= Ta5d6ff"auth"Tb4b4b4;
}Tb4b4b4,
Te6edf3backendOfflineBannerLabelTb4b4b4(Tb4b4b4) {
Te6edf3const Te6edf3duration Tff7b72= Te6edf3thisTb4b4b4.Te6edf3wsDisconnectedDurationTextTb4b4b4;
Te6edf3const Te6edf3durationSuffix Tff7b72= Te6edf3duration Tff7b72? ` · ${Te6edf3duration}` : Ta5d6ff""Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3thisTb4b4b4.Te6edf3backendProcessExitedTb4b4b4) {
Te6edf3const Te6edf3code Tff7b72=
Te6edf3thisTb4b4b4.Te6edf3backendExitCode Tff7b72!= Tff7b72null Tff7b72&Tff7b72& Te6edf3thisTb4b4b4.Te6edf3backendExitCode Tff7b72!=Tff7b72= Ta5d6ff"" Tff7b72? ` Tb4b4b4(${Te6edf3thisTb4b4b4.Te6edf3backendExitCode}Tb4b4b4)` : Ta5d6ff""Tb4b4b4;
Tff7b72return `${Te6edf3thisTb4b4b4.$Te6edf3tTb4b4b4(Ta5d6ff"app.backend_process_stopped"Tb4b4b4)}${Te6edf3code}${Te6edf3durationSuffix}`Tb4b4b4;
}
Tff7b72return `${Te6edf3thisTb4b4b4.$Te6edf3tTb4b4b4(Ta5d6ff"app.backend_disconnected"Tb4b4b4)}${Te6edf3durationSuffix}`Tb4b4b4;
}Tb4b4b4,
Te6edf3showBackendRecoveryActionsTb4b4b4(Tb4b4b4) {
Tff7b72return Tb4b4b4(
Te6edf3thisTb4b4b4.Te6edf3showWsDisconnectedBanner Tff7b72&Tff7b72&
Te6edf3thisTb4b4b4.Te6edf3backendProcessExited Tff7b72&Tff7b72&
Te6edf3ElectronUtilsTb4b4b4.Te6edf3isElectronTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72&
Te6edf3typeof Tff7b72windowTb4b4b4.Te6edf3electronTff7b72?Tb4b4b4.Te6edf3restartBackend Tff7b72=Tff7b72=Tff7b72= Ta5d6ff"function"
Tb4b4b4)Tb4b4b4;
}Tb4b4b4,
Te6edf3showNetworkDegradedBannerTb4b4b4(Tb4b4b4) {
Tff7b72return Tff7b72BooleanTb4b4b4(Te6edf3GlobalStateTb4b4b4.Te6edf3networkDegradedTb4b4b4) Tff7b72&Tff7b72& Te6edf3thisTb4b4b4.$Te6edf3routeTff7b72?Tb4b4b4.Te6edf3name Tff7b72!=Tff7b72= Ta5d6ff"auth"Tb4b4b4;
}Tb4b4b4,
Te6edf3networkDegradedBannerLabelTb4b4b4(Tb4b4b4) {
Te6edf3const Te6edf3detail Tff7b72= Te6edf3GlobalStateTb4b4b4.Te6edf3networkDegradedErrorTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3detailTb4b4b4) {
Tff7b72return `${Te6edf3thisTb4b4b4.$Te6edf3tTb4b4b4(Ta5d6ff"app.network_degraded"Tb4b4b4)}: ${Te6edf3detail}`Tb4b4b4;
}
Tff7b72return Te6edf3thisTb4b4b4.$Te6edf3tTb4b4b4(Ta5d6ff"app.network_degraded"Tb4b4b4)Tb4b4b4;
}Tb4b4b4,
Te6edf3identitySidebarLabelTb4b4b4(Tb4b4b4) {
Te6edf3const Te6edf3raw Tff7b72= Te6edf3thisTb4b4b4.Te6edf3displayNameTb4b4b4;
Te6edf3const Te6edf3name Tff7b72= Te6edf3raw Tff7b72!= Tff7b72null Tff7b72&Tff7b72& Te6edf3StringTb4b4b4(Te6edf3rawTb4b4b4)Tb4b4b4.Tff7b72trimTb4b4b4(Tb4b4b4) Tff7b72!=Tff7b72= Ta5d6ff"" Tff7b72? Te6edf3StringTb4b4b4(Te6edf3rawTb4b4b4)Tb4b4b4.Tff7b72trimTb4b4b4(Tb4b4b4) : Ta5d6ff""Tb4b4b4;
Tff7b72return Te6edf3name Tff7b72|Tff7b72| Te6edf3thisTb4b4b4.$Te6edf3tTb4b4b4(Ta5d6ff"app.my_identity"Tb4b4b4)Tb4b4b4;
}Tb4b4b4,
Te6edf3shellCanvasStyleTb4b4b4(Tb4b4b4) {
Te6edf3const Te6edf3raw Tff7b72= Te6edf3NumberTb4b4b4(Te6edf3thisTb4b4b4.Te6edf3configTff7b72?Tb4b4b4.Te6edf3ui_transparency Tff7b72?Tff7b72? T79c0ff0Tb4b4b4)Tb4b4b4;
Te6edf3const Te6edf3t Tff7b72= Te6edf3NumberTb4b4b4.Te6edf3isFiniteTb4b4b4(Te6edf3rawTb4b4b4) Tff7b72? Te6edf3MathTb4b4b4.Td2a8ffmaxTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3MathTb4b4b4.Td2a8ffminTb4b4b4(T79c0ff100Tb4b4b4, Te6edf3rawTb4b4b4)Tb4b4b4) : T79c0ff0Tb4b4b4;
Te6edf3const Te6edf3factor Tff7b72= Te6edf3t Tff7b72/ T79c0ff100Tb4b4b4;
Te6edf3const Te6edf3alpha Tff7b72= T79c0ff1 Tff7b72- Te6edf3factor Tff7b72* T79c0ff0.42Tb4b4b4;
Te6edf3const Te6edf3isDark Tff7b72= Te6edf3thisTb4b4b4.Te6edf3configTff7b72?Tb4b4b4.Te6edf3theme Tff7b72=Tff7b72=Tff7b72= Ta5d6ff"dark"Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3isDarkTb4b4b4) {
Tff7b72return { Te6edf3backgroundColorTb4b4b4: `Te6edf3rgbaTb4b4b4(T79c0ff9Tb4b4b4, T79c0ff9Tb4b4b4, T79c0ff11Tb4b4b4, ${Te6edf3alpha}Tb4b4b4)` }Tb4b4b4;
}
Tff7b72return { Te6edf3backgroundColorTb4b4b4: `Te6edf3rgbaTb4b4b4(T79c0ff248Tb4b4b4, T79c0ff250Tb4b4b4, T79c0ff252Tb4b4b4, ${Te6edf3alpha}Tb4b4b4)` }Tb4b4b4;
}Tb4b4b4,
}Tb4b4b4,
Te6edf3watchTb4b4b4: {
$Te6edf3routeTb4b4b4(Tff7b72toTb4b4b4, Tff7b72fromTb4b4b4) {
Te6edf3thisTb4b4b4.Te6edf3isSidebarOpen Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72/Tff7b72/ Tff7b72Close Te6edf3tutorial Te6edf3modal Tff7b72if Te6edf3itTa5d6ff's open and we navigate away
if (from && from.name && this.$refs.tutorialModal && this.$refs.tutorialModal.visible) {
this.$refs.tutorialModal.visible = false;
}
},
config: {
handler(newConfig) {
if (newConfig && newConfig.language) {
this.$i18n.locale = newConfig.language;
}
if (newConfig && newConfig.custom_ringtone_enabled !== undefined) {
this.updateRingtonePlayer();
}
if (newConfig && "theme" in newConfig) {
this.applyThemePreference(newConfig.theme ?? "light");
}
this.applyShellAppearance();
NotificationUtils.syncAndroidNotificationContext(
listOpenDestinationHashes(),
Boolean(newConfig?.do_not_disturb_enabled)
);
},
deep: true,
},
isSidebarCollapsed(collapsed) {
saveFeatureSidebarCollapsed("app", collapsed);
},
},
beforeUnmount() {
if (typeof this._shellAuthWatchStop === "function") {
this._shellAuthWatchStop();
this._shellAuthWatchStop = null;
}
if (this._propagationSyncPollTimer != null) {
clearInterval(this._propagationSyncPollTimer);
this._propagationSyncPollTimer = null;
}
// Clear polling guard flag on unmount
this._isPropagationSyncPolling = false;
this.stopShell();
this.clearWsShellUiTimers();
if (this.endedTimeout) clearTimeout(this.endedTimeout);
this.stopRingtone();
this.toneGenerator.stop();
window.removeEventListener("meshchatx-intent-uri", this.onAndroidIntentUri);
window.removeEventListener("pointerdown", this.onRingtoneUnlockGesture, true);
window.removeEventListener("keydown", this.onRingtoneUnlockGesture, true);
if (typeof this._unsubOpenConversations === "function") {
this._unsubOpenConversations();
this._unsubOpenConversations = null;
}
},
mounted() {
try {
const savedSidebarCollapsed = loadFeatureSidebarCollapsed("app");
if (savedSidebarCollapsed !== null) {
this.isSidebarCollapsed = savedSidebarCollapsed;
}
const v = localStorage.getItem("meshchatx_detailed_outbound_send_status");
if (v === "true" || v === "false") {
GlobalState.detailedOutboundSendStatus = v === "true";
}
const tg = localStorage.getItem("meshchatx_message_timestamp_grouping_enabled");
if (tg === "true" || tg === "false") {
GlobalState.messageTimestampGroupingEnabled = tg === "true";
}
const tp = localStorage.getItem("meshchatx_outbound_transfer_progress_enabled");
if (tp === "true" || tp === "false") {
GlobalState.outboundTransferProgressEnabled = tp === "true";
}
} catch {
// ignore
}
this.startShellAuthWatch();
this.applyShellAppearance();
if (ElectronUtils.isElectron()) {
if (typeof window.electron.onBackendProcessExited === "function") {
window.electron.onBackendProcessExited((payload) => {
this.onBackendProcessExited(payload);
});
}
window.electron.onProtocolLink((url) => {
this.handleProtocolLink(url);
});
}
window.addEventListener("meshchatx-intent-uri", this.onAndroidIntentUri);
window.addEventListener("pointerdown", this.onRingtoneUnlockGesture, true);
window.addEventListener("keydown", this.onRingtoneUnlockGesture, true);
this._unsubOpenConversations = subscribeOpenDestinationHashes((hashes) => {
NotificationUtils.syncAndroidNotificationContext(hashes, Boolean(this.config?.do_not_disturb_enabled));
});
NotificationUtils.syncAndroidNotificationContext(
listOpenDestinationHashes(),
Boolean(this.config?.do_not_disturb_enabled)
);
},
methods: {
isNavItemVisible(item) {
if (!item) {
return false;
}
if (item.visibleWhen === "rrcEnabled") {
return this.rrcEnabled;
}
return true;
},
getNavBadgeCount(item) {
if (!item.badge?.source) {
return 0;
}
if (item.badge.source === "unreadConversationsCount") {
return this.unreadConversationsCount;
}
if (item.badge.source === "relayChatUnreadCount") {
return this.relayChatUnreadCount;
}
if (item.badge.source === "missedCallsCount") {
return this.missedCallsCount;
}
return 0;
},
formatNavBadgeCount(item) {
const count = this.getNavBadgeCount(item);
const cap = item.badge?.cap;
if (cap && count >= cap) {
return `${cap - 1}+`;
}
return count;
},
onRingtoneUnlockGesture() {
NotificationSoundUtils.unlockAutoplay();
if (!this.ringtoneAutoplayBlocked) {
return;
}
this.ringtoneAutoplayBlocked = false;
if (this.activeCall?.status === 4 && this.activeCall?.is_incoming) {
this.playRingtone();
}
},
startShellAuthWatch() {
if (typeof this._shellAuthWatchStop === "function") {
this._shellAuthWatchStop();
}
this._shellAuthWatchStop = watch(
() => [
GlobalState.authSessionResolved,
GlobalState.authEnabled,
GlobalState.authenticated,
this.$route?.name,
],
() => this.applyShellAuthState(),
{ immediate: true }
);
},
applyShellAuthState() {
if (!GlobalState.authSessionResolved) {
return;
}
const needShell = !GlobalState.authEnabled || (GlobalState.authenticated && this.$route.name !== "auth");
if (needShell && !this.shellRunning) {
this.startShell();
} else if (!needShell && this.shellRunning) {
this.stopShell();
}
},
startShell() {
if (this.shellRunning) {
return;
}
this.shellRunning = true;
WebSocketConnection.connect();
WebSocketConnection.on("disconnected", this.onWsShellDisconnected);
WebSocketConnection.on("connected", this.onWsShellConnected);
this.registerShellWsHandlers();
this.startClientHeapMemoryWatch();
GlobalEmitter.on("toast-dismissed", this.onToastDismissedShell);
GlobalEmitter.on("identity-switching-start", this.onIdentitySwitchingStartShell);
GlobalEmitter.on("identity-switched-apply", this.onIdentitySwitchedApplyShell);
GlobalEmitter.on("sync-propagation-node", this.onSyncPropagationNodeShell);
GlobalEmitter.on("config-updated", this.onConfigUpdatedExternally);
GlobalEmitter.on("keyboard-shortcut", this.onKeyboardShortcutShell);
GlobalEmitter.on("block-status-changed", this.onBlockStatusChangedShell);
GlobalEmitter.on("show-changelog", this.onShowChangelogShell);
GlobalEmitter.on("show-tutorial", this.onShowTutorialShell);
GlobalEmitter.on("notifications-changed", this.updateUnreadConversationsCount);

this.getAppInfo();
this.getConfig();
this.getBlockedDestinations();
this.getKeyboardShortcuts();
this.updateRingtonePlayer();
this.updateTelephoneStatus();
this.updatePropagationNodeStatus();

GlobalEmitter.on(BATTERY_SAVER_CHANGED_EVENT, this.onBatterySaverPrefsChangedShell);
this.startShellPollIntervals();
this.updateUnreadConversationsCount();
this.updateRelayChatUnreadCount();
},
startShellPollIntervals() {
clearInterval(this.reloadInterval);
clearInterval(this.appInfoInterval);
clearInterval(this.unreadCountInterval);
this.reloadInterval = null;
this.appInfoInterval = null;
this.unreadCountInterval = null;
if (!this.shellRunning) {
return;
}
const prefs = loadBatterySaverPrefs();
this.reloadInterval = setInterval(
() => {
this.updateTelephoneStatus();
this.updatePropagationNodeStatus();
},
applyBackgroundPollInterval(1000, prefs)
);
this.appInfoInterval = setInterval(
() => {
this.getAppInfo();
},
applyBackgroundPollInterval(15000, prefs)
);
this.unreadCountInterval = setInterval(
() => {
this.updateUnreadConversationsCount();
this.updateRelayChatUnreadCount();
},
applyBackgroundPollInterval(5000, prefs)
);
},
onBatterySaverPrefsChangedShell() {
if (this.shellRunning) {
this.startShellPollIntervals();
}
},
onToastDismissedShell({ key }) {
if (key === MEMORY_WARNING_TOAST_KEY) {
markMemoryWarningDismissed();
}
},
startClientHeapMemoryWatch() {
this.stopClientHeapMemoryWatch();
this._clientHeapMemoryTimer = setInterval(() => {
this.sampleClientHeapMemory();
}, CLIENT_HEAP_SAMPLE_INTERVAL_MS);
this.sampleClientHeapMemory();
},
stopClientHeapMemoryWatch() {
if (this._clientHeapMemoryTimer != null) {
clearInterval(this._clientHeapMemoryTimer);
this._clientHeapMemoryTimer = null;
}
},
sampleClientHeapMemory() {
let memoryInfo = null;
try {
memoryInfo = performance?.memory ?? null;
} catch {
memoryInfo = null;
}
const result = evaluateClientHeapSample(memoryInfo);
if (result.shouldWarn) {
showMemoryWarningToastIfNeeded(ToastUtils, { fromClientHeap: true });
}
},
stopShell() {
if (!this.shellRunning) {
return;
}
this.shellRunning = false;
this.stopClientHeapMemoryWatch();
GlobalEmitter.off("toast-dismissed", this.onToastDismissedShell);
clearInterval(this.reloadInterval);
this.reloadInterval = null;
clearInterval(this.appInfoInterval);
this.appInfoInterval = null;
clearInterval(this.unreadCountInterval);
this.unreadCountInterval = null;
GlobalEmitter.off(BATTERY_SAVER_CHANGED_EVENT, this.onBatterySaverPrefsChangedShell);
WebSocketConnection.off("disconnected", this.onWsShellDisconnected);
WebSocketConnection.off("connected", this.onWsShellConnected);
this.unregisterShellWsHandlers();
GlobalEmitter.off("identity-switching-start", this.onIdentitySwitchingStartShell);
GlobalEmitter.off("identity-switched-apply", this.onIdentitySwitchedApplyShell);
GlobalEmitter.off("sync-propagation-node", this.onSyncPropagationNodeShell);
GlobalEmitter.off("config-updated", this.onConfigUpdatedExternally);
GlobalEmitter.off("keyboard-shortcut", this.onKeyboardShortcutShell);
GlobalEmitter.off("block-status-changed", this.onBlockStatusChangedShell);
GlobalEmitter.off("show-changelog", this.onShowChangelogShell);
GlobalEmitter.off("show-tutorial", this.onShowTutorialShell);
GlobalEmitter.off("notifications-changed", this.updateUnreadConversationsCount);
this.clearWsShellUiTimers();
this.wsDisconnected = false;
this.wsDisconnectedAt = null;
this.wsDisconnectedDurationText = "";
this.wsReconnectedBanner = false;
this.backendProcessExited = false;
this.backendExitCode = null;
this.backendRestarting = false;
WebSocketConnection.destroy();
},
clearWsShellUiTimers() {
if (this.wsDisconnectTickTimer != null) {
clearInterval(this.wsDisconnectTickTimer);
this.wsDisconnectTickTimer = null;
}
if (this.wsReconnectedHideTimer != null) {
clearTimeout(this.wsReconnectedHideTimer);
this.wsReconnectedHideTimer = null;
}
},
onBackendProcessExited(payload = {}) {
if (!this.shellRunning) {
return;
}
this.backendProcessExited = true;
this.backendExitCode = payload?.code ?? null;
this.onWsShellDisconnected();
},
async onRestartBackend() {
if (!window.electron?.restartBackend) {
return;
}
this.backendRestarting = true;
try {
const result = await window.electron.restartBackend();
if (!result?.ok) {
ToastUtils.error(result?.error || this.$t("app.restart_backend_failed"));
return;
}
ToastUtils.info(this.$t("app.restart_backend_started"));
} catch {
ToastUtils.error(this.$t("app.restart_backend_failed"));
} finally {
this.backendRestarting = false;
}
},
onOpenInterfacesForRecovery() {
this.$router.push({ name: "interfaces" });
},
async onRecoverNetwork() {
if (this.networkRecovering) {
return;
}
this.networkRecovering = true;
try {
const response = await window.api.post("/api/v1/reticulum/recover", {});
if (response.data?.status?.network_ready) {
GlobalState.networkDegraded = false;
GlobalState.networkDegradedError = null;
ToastUtils.success(response.data.message || this.$t("app.network_recovered"));
return;
}
const err = response.data?.error || response.data?.message || this.$t("app.network_recover_failed");
GlobalState.networkDegradedError = err;
ToastUtils.error(err);
} catch (e) {
const err =
e.response?.data?.error || e.response?.data?.message || this.$t("app.network_recover_failed");
GlobalState.networkDegradedError = err;
ToastUtils.error(err);
} finally {
this.networkRecovering = false;
}
},
async onViewBackendCrashReport() {
if (!window.electron?.openBackendCrashReport) {
return;
}
try {
const result = await window.electron.openBackendCrashReport();
if (!result?.ok) {
ToastUtils.error(result?.error || this.$t("app.view_backend_logs_failed"));
}
} catch {
ToastUtils.error(this.$t("app.view_backend_logs_failed"));
}
},
onWsShellDisconnected() {
if (!this.shellRunning) {
return;
}
this.wsDisconnected = true;
this.wsDisconnectedAt = Date.now();
this._tickWsDisconnectedLabel();
if (this.wsDisconnectTickTimer != null) {
clearInterval(this.wsDisconnectTickTimer);
}
this.wsDisconnectTickTimer = setInterval(() => this._tickWsDisconnectedLabel(), 1000);
},
_tickWsDisconnectedLabel() {
if (!this.wsDisconnectedAt) {
this.wsDisconnectedDurationText = "";
return;
}
this.wsDisconnectedDurationText = formatDisconnectedDuration(Date.now() - this.wsDisconnectedAt);
},
async onWsShellConnected(payload = {}) {
if (!this.shellRunning) {
return;
}
this.wsDisconnected = false;
this.wsDisconnectedAt = null;
this.wsDisconnectedDurationText = "";
this.backendProcessExited = false;
this.backendExitCode = null;
if (this.wsDisconnectTickTimer != null) {
clearInterval(this.wsDisconnectTickTimer);
this.wsDisconnectTickTimer = null;
}
const isReconnect = payload.isReconnect === true;
if (isReconnect) {
await this.resyncShellAfterWebsocketReconnect();
this.wsReconnectedBanner = true;
if (this.wsReconnectedHideTimer != null) {
clearTimeout(this.wsReconnectedHideTimer);
}
this.wsReconnectedHideTimer = setTimeout(() => {
this.wsReconnectedBanner = false;
this.wsReconnectedHideTimer = null;
}, 4500);
}
},
async resyncShellAfterWebsocketReconnect() {
try {
await this.getAppInfo();
} catch {
// ignore
}
try {
await this.getConfig();
} catch {
// ignore
}
try {
await this.getBlockedDestinations();
} catch {
// ignore
}
try {
await this.getKeyboardShortcuts();
} catch {
// ignore
}
try {
await this.updateRingtonePlayer();
} catch {
// ignore
}
try {
await this.updateTelephoneStatus();
} catch {
// ignore
}
try {
await this.updatePropagationNodeStatus();
} catch {
// ignore
}
GlobalEmitter.emit("websocket-reconnected");
},
onIdentitySwitchingStartShell() {
this.isSwitchingIdentity = true;
setTimeout(() => {
if (this.isSwitchingIdentity) {
this.isSwitchingIdentity = false;
}
}, 45000);
},
onIdentitySwitchedApplyShell(payload) {
this.applyIdentitySwitched(payload).catch(() => {});
},
async applyIdentitySwitched(json) {
const hash = json?.identity_hash;
if (hash == null || hash === "") {
return;
}
const now = Date.now();
if (this.identitySwitchDedupeHash === hash && now - this.identitySwitchDedupeAt < 10000) {
return;
}
this.identitySwitchDedupeHash = hash;
this.identitySwitchDedupeAt = now;

ToastUtils.success(this.$t("identities.switched"));

GlobalState.unreadConversationsCount = 0;
GlobalState.missedCallsCount = 0;

await this.getConfig();
await this.updateRingtonePlayer();
await this.getAppInfo();
this.updateTelephoneStatus();

this.isSwitchingIdentity = false;

GlobalEmitter.emit("identity-switched", json);
},
onSyncPropagationNodeShell() {
this.syncPropagationNode();
},
onKeyboardShortcutShell(action) {
this.handleKeyboardShortcut(action);
},
onBlockStatusChangedShell() {
this.getBlockedDestinations();
},
onShowChangelogShell() {
this.$refs.changelogModal?.show();
},
onShowTutorialShell() {
this.$refs.tutorialModal?.show();
},
maybeShowAndroidStorageUpgrade() {
const prompt = this.$refs.androidStorageUpgradePrompt;
if (!prompt || typeof prompt.showUpgrade !== "function") {
return false;
}
return prompt.showUpgrade();
},
async maybeShowPostInstallPrompt() {
const host = this.$refs.postInstallPromptHost;
if (!host || typeof host.showNext !== "function") {
return false;
}
return host.showNext();
},
onAndroidStorageUpgradeCompleted() {
// prompt handles restart when user copies to external storage
},
updateUnreadConversationsCount() {
if (this._unreadCountTimeout) {
clearTimeout(this._unreadCountTimeout);
}
this._unreadCountTimeout = setTimeout(async () => {
try {
const response = await window.api.get("/api/v1/notifications", {
params: { unread: true, limit: 1 },
});
GlobalState.unreadConversationsCount = response.data?.lxmf_total_unread_count ?? 0;
} catch (e) {
console.error("Failed to update unread conversations count", e);
}
}, 300);
},
updateRelayChatUnreadCount() {
if (!this.rrcEnabled) {
GlobalState.relayChatUnreadCount = 0;
return;
}
if (this._relayUnreadCountTimeout) {
clearTimeout(this._relayUnreadCountTimeout);
}
this._relayUnreadCountTimeout = setTimeout(async () => {
try {
const response = await window.api.get("/api/v1/rrc/hubs");
const hubs = response.data?.hubs || [];
GlobalState.relayChatUnreadCount = countRelayMentions(hubs);
} catch (e) {
console.error("Failed to update relay chat mention count", e);
}
}, 300);
},
onConfigUpdatedExternally(newConfig) {
if (!newConfig || typeof newConfig !== "object") {
return;
}
mergeGlobalConfig(newConfig);
this.config = newConfig;
this.displayName = newConfig.display_name;
},
applyThemePreference(theme) {
const mode = theme === "dark" ? "dark" : "light";
if (typeof document !== "undefined") {
document.documentElement.classList.toggle("dark", mode === "dark");
document.documentElement.dataset.bootTheme = mode;
document.documentElement.style.colorScheme = mode;
}
try {
window.localStorage.setItem("meshchatx_ui_theme", mode);
} catch {
// ignore quota / private mode
}
try {
const bridge = window.MeshChatXAndroid;
if (bridge && typeof bridge.setUiTheme === "function") {
bridge.setUiTheme(mode);
}
} catch {
// ignore missing bridge
}
if (typeof this.vuetifyTheme?.change === "function") {
this.vuetifyTheme.change(mode);
}
this.applyShellAppearance();
},
applyShellAppearance() {
if (typeof document === "undefined") {
return;
}
const glassOn = this.config?.ui_glass_enabled !== false;
document.documentElement.dataset.uiGlass = glassOn ? "1" : "0";
},
getHashPopoutValue() {
const hash = window.location.hash || "";
const match = hash.match(/popout=([^&]+)/);
return match ? decodeURIComponent(match[1]) : null;
},
registerShellWsHandlers() {
this.unregisterShellWsHandlers();
const handlers = this.getShellWsHandlers();
for (const [type, handler] of Object.entries(handlers)) {
const bound = (payload) => handler(payload);
onWsEvent(type, bound);
this.shellWsHandlerCleanups.push(() => offWsEvent(type, bound));
}
},
unregisterShellWsHandlers() {
for (const cleanup of this.shellWsHandlerCleanups) {
cleanup();
}
this.shellWsHandlerCleanups = [];
},
getShellWsHandlers() {
return {
config: (json) => {
const next = json?.config;
if (next && typeof next === "object") {
mergeGlobalConfig(next);
this.config = next;
this.displayName = next.display_name;
}
},
keyboard_shortcuts: (json) => {
KeyboardShortcuts.setShortcuts(json.shortcuts);
},
announced: () => {
this.getConfig();
},
telephone_ringing: (json) => {
if (this.config?.do_not_disturb_enabled) {
return;
}
if (
(this.config?.telephone_allow_calls_from_contacts_only ||
this.config?.block_all_from_strangers) &&
!json.is_contact
) {
return;
}
if (this.initiationStatus) {
return;
}
NotificationUtils.showIncomingCallNotification(
json.remote_identity_name || json.remote_identity_hash
);
this.updateTelephoneStatus();
this.playRingtone();
},
telephone_missed_call: (json) => {
NotificationUtils.showMissedCallNotification(
json.remote_identity_name || json.remote_identity_hash
);
this.updateTelephoneStatus();
},
telephone_initiation_status: (json) => {
this.initiationStatus = json.status;
this.initiationTargetHash = json.target_hash;
this.initiationTargetName = json.target_name;

if (this.initiationStatus === "Ringing...") {
if (this.config?.telephone_tone_generator_enabled) {
this.toneGenerator.setVolume(this.config.telephone_tone_generator_volume);
this.toneGenerator.playRingback();
}
} else if (this.initiationStatus === null) {
this.toneGenerator.stop();
}
},
new_voicemail: (json) => {
NotificationUtils.showNewVoicemailNotification(
json.remote_identity_name || json.remote_identity_hash
);
this.updateTelephoneStatus();
},
telephone_call_established: () => {
this.stopRingtone();
this.ringtonePlayer = null;
this.toneGenerator.stop();
NotificationUtils.cancelIncomingCallNotification();
this.updateTelephoneStatus();
// Ensure CallPage is mounted so Android native audio / web
// audio can attach after answer from overlay or notification.
if (this.$route?.name !== "call" || this.$route?.query?.tab !== "phone") {
this.$router.push({ name: "call", query: { tab: "phone" } });
}
},
telephone_call_ended: () => {
this.stopRingtone();
NotificationUtils.cancelIncomingCallNotification();
this.ringtonePlayer = null;
if (this.config?.telephone_tone_generator_enabled) {
this.toneGenerator.setVolume(this.config.telephone_tone_generator_volume);
this.toneGenerator.playBusyTone();
}
this.updateTelephoneStatus();
},
blocked_destinations: (json) => {
GlobalState.blockedDestinations = json.blocked_destinations || [];
},
"rrc.message": (json) => {
if (json.mention || json.message?.mention) {
this.updateRelayChatUnreadCount();
}
},
"rrc.change": () => {
this.updateRelayChatUnreadCount();
},
"lxmf.delivery": async (json) => {
if (this.config?.do_not_disturb_enabled) {
return;
}
if (json.sieve_suppress_notifications) {
return;
}
const lxmfMessage = json.lxmf_message;
const isIncoming = lxmfMessage?.is_incoming === true;
const userFacing = isUserFacingLxmfDeliveryMessage(lxmfMessage);
const sourceHash = deliverySourceHash(json);
const openHashes = listOpenDestinationHashes();
const sourceOpen = openHashes.includes(String(sourceHash || "").toLowerCase());
const hasFocus = typeof document !== "undefined" ? document.hasFocus() : true;
const policyBase = {
isIncoming,
sieveSuppress: Boolean(json.sieve_suppress_notifications),
dnd: Boolean(this.config?.do_not_disturb_enabled),
hasFocus,
openDestinationHashes: openHashes,
sourceHash,
userFacing,
};

// Open peers are mark-as-read by ConversationViewer; still refresh for other peers.
if (isIncoming && userFacing && !sourceOpen) {
this.updateUnreadConversationsCount();
}

let playedNotificationSound = false;
if (shouldPlayMessageSound(policyBase)) {
playedNotificationSound = await NotificationSoundUtils.play(this.config);
}
if (shouldShowOsMessageNotification(policyBase)) {
NotificationUtils.showNewMessageNotification(
json.remote_identity_name,
lxmfMessage?.content || lxmfMessage?.title || "",
playedNotificationSound,
sourceHash
);
}
},
"lxm.ingest_uri.result": async (json) => {
const handled = await handleLxmIngestUriResult(json, {
router: this.$router,
toast: ToastUtils,
});
if (handled) {
return;
}
if (json.status === "success") {
ToastUtils.success(json.message);
} else if (json.status === "error") {
ToastUtils.error(json.message);
} else if (json.status === "warning") {
ToastUtils.warning(json.message);
} else {
ToastUtils.info(json.message);
}
},
database_health_warning: (json) => {
if (json.issues && json.issues.length > 0) {
ToastUtils.warning(json.issues.join(" ") || "Database issue detected.", 8000);
}
},
health_warning: (json) => {
handleHealthWarningPayload(json, ToastUtils);
},
identity_switched: async (json) => {
await this.applyIdentitySwitched(json);
},
"rncp.receive.completed": (json) => {
if (this.$route?.name !== "rncp") {
const detail =
json.status === "completed" && json.saved_path
? json.saved_path
: json.error || json.status || "";
if (json.status === "completed") {
ToastUtils.success(`${this.$t("rncp.received_file")}${detail ? ": " + detail : ""}`);
if (ElectronUtils.isElectron()) {
ElectronUtils.showNotification(this.$t("rncp.received_file"), detail || "");
}
} else {
ToastUtils.error(`${this.$t("rncp.receive_failed")}${detail ? ": " + detail : ""}`);
}
}
},
};
},
async getAppInfo() {
try {
const response = await window.api.get(`/api/v1/app/info`);
this.appInfo = response.data.app_info;

if (this.appInfo.database_health_issues && this.appInfo.database_health_issues.length > 0) {
const msg =
this.appInfo.database_health_issues.join(" ") ||
"Database issue detected. Check About > Database.";
ToastUtils.warning(msg, 8000);
}

// check URL params for modal triggers
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has("show-guide")) {
this.$refs.tutorialModal.show();
// remove param from URL
urlParams.delete("show-guide");
const newUrl = window.location.pathname + (urlParams.toString() ? `?${urlParams.toString()}` : "");
window.history.replaceState({}, "", newUrl);
} else if (urlParams.has("changelog")) {
this.$refs.changelogModal.show();
// remove param from URL
urlParams.delete("changelog");
const newUrl = window.location.pathname + (urlParams.toString() ? `?${urlParams.toString()}` : "");
window.history.replaceState({}, "", newUrl);
} else if (!this.hasCheckedForModals) {
// check if we should show tutorial or changelog (only on first load)
this.hasCheckedForModals = true;
if (this.appInfo && !this.appInfo.tutorial_seen) {
this.$refs.tutorialModal.show();
} else if (this.maybeShowAndroidStorageUpgrade()) {
// upgrade prompt for existing internal-storage installs
} else if (await this.maybeShowPostInstallPrompt()) {
// registry prompts for existing users (bump revision to re-show)
} else if (
this.appInfo &&
this.appInfo.changelog_seen_version !== "999.999.999" &&
this.appInfo.changelog_seen_version !== this.appInfo.version
) {
// show changelog if version changed and not silenced forever
this.$refs.changelogModal.show();
}
}
} catch (e) {
// do nothing if failed to load app info
console.log(e);
}
},
async getConfig() {
try {
const response = await window.api.get(`/api/v1/config`);
const next = response.data?.config;
if (next && typeof next === "object") {
mergeGlobalConfig(next);
this.config = next;
this.displayName = next.display_name;
}
} catch (e) {
// do nothing if failed to load config
console.log(e);
}
},
async getBlockedDestinations() {
try {
const response = await window.api.get("/api/v1/blocked-destinations");
GlobalState.blockedDestinations = response.data.blocked_destinations || [];
} catch (e) {
console.log("Failed to load blocked destinations:", e);
}
},
async getKeyboardShortcuts() {
WebSocketConnection.send(
JSON.stringify({
type: "keyboard_shortcuts.get",
})
);
},
async sendAnnounce() {
try {
await window.api.get(`/api/v1/announce`);
ToastUtils.success(this.$t("app.announce_sent"));
} catch (e) {
ToastUtils.error(this.$t("app.failed_announce"));
console.log(e);
}

await this.getConfig();
},
async copyValue(value, label) {
if (!value) return;
try {
await navigator.clipboard.writeText(value);
ToastUtils.success(`${label} copied`);
} catch {
ToastUtils.success(value);
}
},
async openLxmfQr() {
if (!this.config?.lxmf_address_hash) return;
try {
const uri = this.getMyIdentityUri();
this.lxmfQrDataUrl = await QRCode.toDataURL(uri, { margin: 1, scale: 6 });
this.showLxmfQr = true;
} catch {
ToastUtils.error(this.$t("common.error"));
}
},
getMyIdentityUri() {
if (!this.config?.lxmf_address_hash) return null;
const publicKey = this.config?.identity_public_key;
return publicKey
? `lxma://${this.config.lxmf_address_hash}:${publicKey}`
: `lxmf://${this.config.lxmf_address_hash}`;
},
async copyIdentityUri() {
const uri = this.getMyIdentityUri();
if (!uri) return;
await this.copyValue(uri, "Identity URI");
},
async updateConfig(config, label = null) {
try {
WebSocketConnection.send(
JSON.stringify({
type: "config.set",
config: config,
})
);
if (label) {
ToastUtils.success(
this.$t("app.setting_auto_saved", {
label: this.$t(`app.${label.toLowerCase().replace(/ /g, "_")}`),
})
);
}
} catch (e) {
console.error(e);
}
},
async saveIdentitySettings() {
await this.updateConfig(
{
display_name: this.displayName,
},
"display_name_placeholder"
);
},
async onAnnounceIntervalSecondsChange() {
await this.updateConfig(
{
auto_announce_interval_seconds: this.config.auto_announce_interval_seconds,
},
"announce_interval"
);
},
async toggleTheme() {
if (!this.config) {
return;
}
const newTheme = this.config.theme === "dark" ? "light" : "dark";
await this.updateConfig(
{
theme: newTheme,
},
"theme"
);
},
async onLanguageChange(langCode) {
await this.updateConfig(
{
language: langCode,
},
"language"
);
this.$i18n.locale = langCode;
},
async composeNewMessage() {
// go to messages route
await this.$router.push({ name: "messages" });

// emit global event handled by MessagesPage
GlobalEmitter.emit("compose-new-message");
},
async syncPropagationNode() {
const propagationSyncToastKey = "propagation-sync-status";
// ask to stop syncing if already syncing
if (this.isSyncingPropagationNode) {
if (await DialogUtils.confirm(this.$t("app.stop_sync_confirm"))) {
await this.stopSyncingPropagationNode();
}
return;
}

this.userInitiatedPropagationSync = true;

// request sync
try {
const preferredHash = this.config?.lxmf_preferred_propagation_node_destination_hash;
if (preferredHash) {
await postRequestPath(window.api, preferredHash);
}
await window.api.get("/api/v1/lxmf/propagation-node/sync");
} catch (e) {
this.userInitiatedPropagationSync = false;
const errorMessage = e.response?.data?.message ?? this.$t("app.sync_error_generic");
ToastUtils.error(errorMessage);
return;
}

await this.updatePropagationNodeStatus();

// Guard to prevent overlapping poll calls
this._isPropagationSyncPolling = false;
const pollStartedAt = Date.now();
const propagationSyncPollTimeoutMs = 120000;

const poll = async () => {
if (this._isPropagationSyncPolling) return;
this._isPropagationSyncPolling = true;
try {
await this.updatePropagationNodeStatus();
if (this.isSyncingPropagationNode) {
if (Date.now() - pollStartedAt > propagationSyncPollTimeoutMs) {
if (this._propagationSyncPollTimer != null) {
clearInterval(this._propagationSyncPollTimer);
this._propagationSyncPollTimer = null;
}
await this.stopSyncingPropagationNode();
this.userInitiatedPropagationSync = false;
ToastUtils.error(
this.$t("app.sync_error", {
status: this.propagationSyncStatusLabel("path_timeout"),
})
);
return;
}
ToastUtils.loading(this.propagationSyncLiveToastMessage(), 0, propagationSyncToastKey);
return;
}
if (this._propagationSyncPollTimer != null) {
clearInterval(this._propagationSyncPollTimer);
this._propagationSyncPollTimer = null;
}
this.userInitiatedPropagationSync = false;
ToastUtils.dismiss(propagationSyncToastKey);
const status = this.propagationNodeStatus?.state;
const messagesReceived = this.propagationNodeStatus?.messages_received ?? 0;
const messagesStored = this.propagationNodeStatus?.messages_stored ?? 0;
const deliveryConfirmations = this.propagationNodeStatus?.delivery_confirmations ?? 0;
const messagesHidden = this.propagationNodeStatus?.messages_hidden ?? 0;
if (status === "complete" || status === "idle") {
const base = this.$t("app.sync_complete", { count: messagesReceived });
const details = `${messagesStored} stored, ${deliveryConfirmations} confirmations, ${messagesHidden} hidden`;
ToastUtils.success(`${base} (${details})`);
} else {
ToastUtils.error(
this.$t("app.sync_error", {
status: this.propagationSyncStatusLabel(status),
})
);
}
} finally {
this._isPropagationSyncPolling = false;
}
};

if (this.isSyncingPropagationNode) {
ToastUtils.loading(this.propagationSyncLiveToastMessage(), 0, propagationSyncToastKey);
this._propagationSyncPollTimer = setInterval(poll, 500);
} else {
this.userInitiatedPropagationSync = false;
}
await poll();
},
propagationSyncStatusLabel(state) {
if (state == null || state === "") {
return this.$t("app.propagation_sync_state.unknown");
}
const key = `app.propagation_sync_state.${state}`;
const translated = this.$t(key);
return translated !== key ? translated : this.$t("app.propagation_sync_state.unknown");
},
propagationSyncLiveToastMessage() {
const status = this.propagationNodeStatus?.state ?? "unknown";
const progress = Math.round(this.propagationNodeStatus?.progress ?? 0);
return this.$t("app.propagation_sync_live", {
status: this.propagationSyncStatusLabel(status),
progress,
});
},
async stopSyncingPropagationNode() {
const propagationSyncToastKey = "propagation-sync-status";
try {
await window.api.get("/api/v1/lxmf/propagation-node/stop-sync");
} catch {
// do nothing on error
}
if (this._propagationSyncPollTimer != null) {
clearInterval(this._propagationSyncPollTimer);
this._propagationSyncPollTimer = null;
}
// Clear the polling guard flag
this._isPropagationSyncPolling = false;
this.userInitiatedPropagationSync = false;
ToastUtils.dismiss(propagationSyncToastKey);
await this.updatePropagationNodeStatus();
},
async updatePropagationNodeStatus() {
try {
const response = await window.api.get("/api/v1/lxmf/propagation-node/status");
this.propagationNodeStatus = response.data.propagation_node_status;
const state = this.propagationNodeStatus?.state;
if (
this.userInitiatedPropagationSync &&
state &&
![
"path_requested",
"link_establishing",
"link_established",
"request_sent",
"receiving",
"response_received",
].includes(state)
) {
this.userInitiatedPropagationSync = false;
}
} catch {
// do nothing on error
}
},
formatSecondsAgo: function (seconds) {
return Utils.formatSecondsAgo(seconds);
},
async updateRingtonePlayer() {
// Stop current player if any
if (this.ringtonePlayer) {
this.ringtonePlayer.pause();
this.ringtonePlayer = null;
}

if (this.config?.custom_ringtone_enabled) {
try {
const response = await window.api.get("/api/v1/telephone/ringtones/status");
const status = response.data;
if (status.has_custom_ringtone && status.id) {
this.ringtonePlayer = new Audio(`/api/v1/telephone/ringtones/${status.id}/audio`);
this.ringtonePlayer.loop = true;
if (status.volume !== undefined) {
this.ringtonePlayer.volume = status.volume;
}
}
} catch (e) {
console.error("Failed to update ringtone player:", e);
}
}
},
playRingtone() {
if (!this.ringtonePlayer || this.ringtoneAutoplayBlocked) {
return;
}
if (this.ringtonePlayer.paused) {
this.ringtonePlayer.play().catch((e) => {
if (e?.name === "NotAllowedError") {
// Browser autoplay policy blocked playback until user gesture.
// Stop retry spam; we retry once user interacts again.
this.ringtoneAutoplayBlocked = true;
return;
}
console.warn("Failed to play custom ringtone:", e);
});
}
},
stopRingtone() {
if (this.ringtonePlayer) {
try {
this.ringtonePlayer.pause();
this.ringtonePlayer.currentTime = 0;
} catch {
// ignore errors during pause
}
}
},
async updateTelephoneStatus() {
try {
// fetch status
const response = await window.api.get("/api/v1/telephone/status");
const oldCall = this.activeCall;
const newCall = response.data.active_call;

// update ui
this.activeCall = newCall;
if (this.activeCall) {
this.toneGenerator.stop();
}
this.voicemailStatus = response.data.voicemail;
this.initiationStatus = response.data.initiation_status;
this.initiationTargetHash = response.data.initiation_target_hash;
this.initiationTargetName = response.data.initiation_target_name;
GlobalState.missedCallsCount = response.data?.missed_calls_unread_count ?? 0;

// Update call ended state if needed
const justEnded = oldCall != null && this.activeCall == null;
if (justEnded) {
this.lastCall = oldCall;
if (this.config?.telephone_tone_generator_enabled) {
this.toneGenerator.setVolume(this.config.telephone_tone_generator_volume);
this.toneGenerator.playBusyTone();
}

// Trigger history refresh
GlobalEmitter.emit("telephone-history-updated");

if (!this.wasDeclined) {
this.isCallEnded = true;
}

if (this.endedTimeout) clearTimeout(this.endedTimeout);
this.endedTimeout = setTimeout(() => {
this.isCallEnded = false;
this.wasDeclined = false;
this.lastCall = null;
}, 5000);
}

// Handle outgoing ringback tone
if (this.initiationStatus === "Ringing...") {
if (this.config?.telephone_tone_generator_enabled) {
this.toneGenerator.setVolume(this.config.telephone_tone_generator_volume);
this.toneGenerator.playRingback();
}
} else if (!this.initiationStatus && !this.activeCall && !this.isCallEnded) {
// Only stop if we'Te6edf3re Tff7b72not Te6edf3ringingTb4b4b4, Tff7b72in Te6edf3a Tff7b72callTb4b4b4, Tff7b72or Te6edf3just Te6edf3finished Te6edf3a Tff7b72call Tb4b4b4(Te6edf3busy Te6edf3tone Te6edf3playingTb4b4b4)
Te6edf3thisTb4b4b4.Te6edf3toneGeneratorTb4b4b4.Te6edf3stopTb4b4b4(Tb4b4b4)Tb4b4b4;
}

Tff7b72/Tff7b72/ Te6edf3Handle Td2a8ffpower Te6edf3management Tff7b72for Te6edf3calls
Tff7b72if Tb4b4b4(Te6edf3ElectronUtilsTb4b4b4.Te6edf3isElectronTb4b4b4(Tb4b4b4)Tb4b4b4) {
Tff7b72if Tb4b4b4(Te6edf3thisTb4b4b4.Te6edf3activeCallTb4b4b4) {
Tff7b72windowTb4b4b4.Te6edf3electronTb4b4b4.Te6edf3setPowerSaveBlockerTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
} Tff7b72else Tff7b72if Tb4b4b4(!Te6edf3thisTb4b4b4.Te6edf3initiationStatusTb4b4b4) {
Tff7b72windowTb4b4b4.Te6edf3electronTb4b4b4.Te6edf3setPowerSaveBlockerTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
}
}

Tff7b72/Tff7b72/ Te6edf3Handle Te6edf3opening Tff7b72call Tff7b72in Te6edf3separate Tff7b72window Tff7b72if Te6edf3enabled
Tff7b72if Tb4b4b4(
Tb4b4b4(Te6edf3thisTb4b4b4.Te6edf3activeCall Tff7b72|Tff7b72| Te6edf3thisTb4b4b4.Te6edf3initiationStatusTb4b4b4) Tff7b72&Tff7b72&
Te6edf3thisTb4b4b4.Te6edf3configTff7b72?Tb4b4b4.Te6edf3desktop_open_calls_in_separate_window Tff7b72&Tff7b72&
Te6edf3ElectronUtilsTb4b4b4.Te6edf3isElectronTb4b4b4(Tb4b4b4)
Tb4b4b4) {
Tff7b72if Tb4b4b4(!Te6edf3thisTb4b4b4.Te6edf3isCallWindowOpen Tff7b72&Tff7b72& !Te6edf3thisTb4b4b4.$Te6edf3routeTb4b4b4.Te6edf3metaTb4b4b4.Te6edf3isPopoutTb4b4b4) {
Te6edf3thisTb4b4b4.Te6edf3isCallWindowOpen Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72windowTb4b4b4.Tff7b72openTb4b4b4(Ta5d6ff"/call.html"Tb4b4b4, Ta5d6ff"MeshChatXCallWindow"Tb4b4b4, Ta5d6ff"width=600,height=800"Tb4b4b4)Tb4b4b4;
}
} Tff7b72else {
Te6edf3thisTb4b4b4.Te6edf3isCallWindowOpen Tff7b72= Tff7b72falseTb4b4b4;
}

Tff7b72/Tff7b72/ Te6edf3Handle Te6edf3ringtone Tb4b4b4(Tff7b72only Tff7b72for Te6edf3incoming Te6edf3ringingTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3thisTb4b4b4.Te6edf3activeCallTff7b72?Tb4b4b4.Te6edf3status Tff7b72=Tff7b72=Tff7b72= T79c0ff4 Tff7b72&Tff7b72& Te6edf3thisTb4b4b4.Te6edf3activeCallTff7b72?Tb4b4b4.Te6edf3is_incomingTb4b4b4) {
Tff7b72/Tff7b72/ Tff7b72Call Tff7b72is Te6edf3ringing
Tff7b72if Tb4b4b4(!Te6edf3thisTb4b4b4.Te6edf3ringtonePlayer Tff7b72&Tff7b72& Te6edf3thisTb4b4b4.Te6edf3configTff7b72?Tb4b4b4.Te6edf3custom_ringtone_enabled Tff7b72&Tff7b72& !Te6edf3thisTb4b4b4.Te6edf3isFetchingRingtoneTb4b4b4) {
Te6edf3thisTb4b4b4.Te6edf3isFetchingRingtone Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72try {
Te6edf3const Te6edf3caller_hash Tff7b72= Te6edf3thisTb4b4b4.Te6edf3activeCallTb4b4b4.Te6edf3remote_identity_hashTb4b4b4;
Te6edf3const Te6edf3ringResponse Tff7b72= Te6edf3await Tff7b72windowTb4b4b4.Te6edf3apiTb4b4b4.Tff7b72getTb4b4b4(
`Tff7b72/Te6edf3apiTff7b72/Te6edf3v1Tff7b72/Te6edf3telephoneTff7b72/Te6edf3ringtonesTff7b72/Te6edf3statusTff7b72?Te6edf3caller_hashTff7b72=${Te6edf3caller_hash}`
Tb4b4b4)Tb4b4b4;
Te6edf3const Te6edf3status Tff7b72= Te6edf3ringResponseTb4b4b4.Tff7b72dataTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3statusTb4b4b4.Te6edf3has_custom_ringtone Tff7b72&Tff7b72& Te6edf3statusTb4b4b4.Te6edf3idTb4b4b4) {
Tff7b72/Tff7b72/ Tff7b72Double Tff7b72check Tff7b72if Te6edf3we Te6edf3still Te6edf3need Tff7b72to Te6edf3play Te6edf3it Tb4b4b4(Tff7b72call Te6edf3might Te6edf3have Te6edf3ended Te6edf3during Te6edf3awaitTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3thisTb4b4b4.Te6edf3activeCallTff7b72?Tb4b4b4.Te6edf3status Tff7b72=Tff7b72=Tff7b72= T79c0ff4Tb4b4b4) {
Tff7b72/Tff7b72/ Te6edf3Stop Tff7b72any Te6edf3existing Te6edf3player Te6edf3just Tff7b72in Tff7b72case
Te6edf3thisTb4b4b4.Te6edf3stopRingtoneTb4b4b4(Tb4b4b4)Tb4b4b4;

Te6edf3thisTb4b4b4.Te6edf3ringtonePlayer Tff7b72= Tff7b72new Te6edf3AudioTb4b4b4(`Tff7b72/Te6edf3apiTff7b72/Te6edf3v1Tff7b72/Te6edf3telephoneTff7b72/Te6edf3ringtonesTff7b72/${Te6edf3statusTb4b4b4.Te6edf3id}Tff7b72/Te6edf3audio`Tb4b4b4)Tb4b4b4;
Te6edf3thisTb4b4b4.Te6edf3ringtonePlayerTb4b4b4.Te6edf3loop Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3statusTb4b4b4.Te6edf3volume Tff7b72!=Tff7b72= Te6edf3undefinedTb4b4b4) {
Te6edf3thisTb4b4b4.Te6edf3ringtonePlayerTb4b4b4.Te6edf3volume Tff7b72= Te6edf3statusTb4b4b4.Te6edf3volumeTb4b4b4;
}
Te6edf3thisTb4b4b4.Te6edf3playRingtoneTb4b4b4(Tb4b4b4)Tb4b4b4;
}
}
} Te6edf3finally {
Te6edf3thisTb4b4b4.Te6edf3isFetchingRingtone Tff7b72= Tff7b72falseTb4b4b4;
}
} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3thisTb4b4b4.Te6edf3ringtonePlayer Tff7b72&Tff7b72& Te6edf3thisTb4b4b4.Te6edf3activeCallTff7b72?Tb4b4b4.Te6edf3status Tff7b72=Tff7b72=Tff7b72= T79c0ff4Tb4b4b4) {
Te6edf3thisTb4b4b4.Te6edf3playRingtoneTb4b4b4(Tb4b4b4)Tb4b4b4;
}
} Tff7b72else {
Tff7b72/Tff7b72/ Tff7b72Not Te6edf3ringing
Tff7b72if Tb4b4b4(Te6edf3thisTb4b4b4.Te6edf3ringtonePlayerTb4b4b4) {
Te6edf3thisTb4b4b4.Te6edf3stopRingtoneTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3thisTb4b4b4.Te6edf3ringtonePlayer Tff7b72= Tff7b72nullTb4b4b4;
}
}

Tff7b72/Tff7b72/ Tff7b72Preserve Tff7b72local Te6edf3mute Tff7b72state Tff7b72if Te6edf3we'Te6edf3re Te6edf3currently Te6edf3toggling
Tff7b72if Tb4b4b4(Te6edf3newCall Tff7b72&Tff7b72& Te6edf3oldCallTb4b4b4) {
Te6edf3newCallTb4b4b4.Te6edf3is_mic_muted Tff7b72= Te6edf3oldCallTb4b4b4.Te6edf3is_mic_mutedTb4b4b4;
Te6edf3newCallTb4b4b4.Te6edf3is_speaker_muted Tff7b72= Te6edf3oldCallTb4b4b4.Te6edf3is_speaker_mutedTb4b4b4;
}

Tff7b72/Tff7b72/ Tff7b72If Tff7b72call Te6edf3just Te6edf3endedTb4b4b4, Te6edf3show Te6edf3ended Tff7b72state Tff7b72for Te6edf3a Te6edf3few Te6edf3seconds
Tff7b72if Tb4b4b4(Te6edf3justEndedTb4b4b4) {
Tff7b72/Tff7b72/ Te6edf3Handled Te6edf3above
} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3thisTb4b4b4.Te6edf3activeCall Tff7b72!= Tff7b72nullTb4b4b4) {
Tff7b72/Tff7b72/ Tff7b72if Te6edf3a Tff7b72new Tff7b72call Te6edf3startsTb4b4b4, Te6edf3clear Te6edf3ended Tff7b72state
Te6edf3thisTb4b4b4.Te6edf3isCallEnded Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3thisTb4b4b4.Te6edf3wasDeclined Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3thisTb4b4b4.Te6edf3lastCall Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3thisTb4b4b4.Te6edf3endedTimeoutTb4b4b4) Te6edf3clearTimeoutTb4b4b4(Te6edf3thisTb4b4b4.Te6edf3endedTimeoutTb4b4b4)Tb4b4b4;
} Tff7b72else Tff7b72if Tb4b4b4(!Te6edf3thisTb4b4b4.Te6edf3endedTimeoutTb4b4b4) {
Tff7b72/Tff7b72/ Tff7b72If Tff7b72no Tff7b72call Tff7b72and Tff7b72no Te6edf3ended Tff7b72state Te6edf3timeout Te6edf3activeTb4b4b4, Te6edf3ensure Te6edf3everything Tff7b72is Te6edf3reset
Te6edf3thisTb4b4b4.Te6edf3isCallEnded Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3thisTb4b4b4.Te6edf3wasDeclined Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3thisTb4b4b4.Te6edf3lastCall Tff7b72= Tff7b72nullTb4b4b4;
}
} Tff7b72catch {
Tff7b72/Tff7b72/ Te6edf3do Te6edf3nothing Tff7b72on Te6edf3error
}
}Tb4b4b4,
Te6edf3onOverlayHangupTb4b4b4(Tb4b4b4) {
Tff7b72if Tb4b4b4(Te6edf3thisTb4b4b4.Te6edf3activeCall Tff7b72&Tff7b72& Te6edf3thisTb4b4b4.Te6edf3activeCallTb4b4b4.Te6edf3is_incoming Tff7b72&Tff7b72& Te6edf3thisTb4b4b4.Te6edf3activeCallTb4b4b4.Te6edf3status Tff7b72=Tff7b72=Tff7b72= T79c0ff4Tb4b4b4) {
Te6edf3thisTb4b4b4.Te6edf3wasDeclined Tff7b72= Tff7b72trueTb4b4b4;
}
}Tb4b4b4,
Te6edf3onToggleMicTb4b4b4(Te6edf3isMutedTb4b4b4) {
Te6edf3thisTb4b4b4.Te6edf3isMicMuting Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3thisTb4b4b4.Te6edf3activeCallTb4b4b4) {
Te6edf3thisTb4b4b4.Te6edf3activeCallTb4b4b4.Te6edf3is_mic_muted Tff7b72= Te6edf3isMutedTb4b4b4;
}
Te6edf3setTimeoutTb4b4b4(Tb4b4b4(Tb4b4b4) Tff7b72=Tff7b72> {
Te6edf3thisTb4b4b4.Te6edf3isMicMuting Tff7b72= Tff7b72falseTb4b4b4;
}Tb4b4b4, T79c0ff2000Tb4b4b4)Tb4b4b4;
}Tb4b4b4,
Te6edf3onToggleSpeakerTb4b4b4(Te6edf3isMutedTb4b4b4) {
Te6edf3thisTb4b4b4.Te6edf3isSpeakerMuting Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3thisTb4b4b4.Te6edf3activeCallTb4b4b4) {
Te6edf3thisTb4b4b4.Te6edf3activeCallTb4b4b4.Te6edf3is_speaker_muted Tff7b72= Te6edf3isMutedTb4b4b4;
}
Te6edf3setTimeoutTb4b4b4(Tb4b4b4(Tb4b4b4) Tff7b72=Tff7b72> {
Te6edf3thisTb4b4b4.Te6edf3isSpeakerMuting Tff7b72= Tff7b72falseTb4b4b4;
}Tb4b4b4, T79c0ff2000Tb4b4b4)Tb4b4b4;
}Tb4b4b4,
Te6edf3onAppNameClickTb4b4b4(Tb4b4b4) {
Tff7b72/Tff7b72/ Tff7b72user Te6edf3may Te6edf3be Tff7b72on Te6edf3mobileTb4b4b4, Tff7b72and Tff7b72is Te6edf3unable Tff7b72to Tff7b72scroll Te6edf3back Tff7b72to Te6edf3sidebarTb4b4b4, Te6edf3so Te6edf3let Te6edf3them Te6edf3tap Te6edf3app Te6edf3name Tff7b72to Te6edf3do Te6edf3it
Te6edf3thisTb4b4b4.$Te6edf3refsTff7b72[Te6edf3"middle"Tff7b72]Tff7b72?Tb4b4b4.Te6edf3scrollToTb4b4b4({
Tff7b72top: T79c0ff0Tb4b4b4,
Td2a8ffleft: T79c0ff0Tb4b4b4,
Te6edf3behaviorTb4b4b4: Ta5d6ff"smooth"Tb4b4b4,
}Tb4b4b4)Tb4b4b4;
Te6edf3thisTb4b4b4.$Te6edf3routerTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff"/messages"Tb4b4b4)Tb4b4b4;
}Tb4b4b4,
Te6edf3onAndroidIntentUriTb4b4b4(Te6edf3eventTb4b4b4) {
Te6edf3const Te6edf3uri Tff7b72= Te6edf3eventTff7b72?Tb4b4b4.Te6edf3detailTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3typeof Te6edf3uri Tff7b72!=Tff7b72= Ta5d6ff"string" Tff7b72|Tff7b72| Te6edf3uriTb4b4b4.Tff7b72trimTb4b4b4(Tb4b4b4) Tff7b72=Tff7b72=Tff7b72= Ta5d6ff""Tb4b4b4) {
Tff7b72returnTb4b4b4;
}
Te6edf3thisTb4b4b4.Te6edf3handleProtocolLinkTb4b4b4(Te6edf3uriTb4b4b4.Tff7b72trimTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
}Tb4b4b4,
Te6edf3handleProtocolLinkTb4b4b4(Te6edf3urlTb4b4b4) {
Tff7b72try {
Te6edf3const Te6edf3normalizedUrl Tff7b72= Te6edf3StringTb4b4b4(Te6edf3url Tff7b72|Tff7b72| Ta5d6ff""Tb4b4b4)Tb4b4b4.Tff7b72trimTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(!Te6edf3normalizedUrlTb4b4b4) {
Tff7b72returnTb4b4b4;
}
Tff7b72if Tb4b4b4(Tff7b72/Tff7b72^Te6edf3meshchatxTb4b4b4:\Tff7b72/\Tff7b72/Te6edf3app\Tff7b72/Te6edf3messages\Tff7b72/Tff7b72?Tff7b72/Te6edf3iTb4b4b4.Te6edf3testTb4b4b4(Te6edf3normalizedUrlTb4b4b4)Tb4b4b4) {
Te6edf3thisTb4b4b4.$Te6edf3routerTb4b4b4.Te6edf3pushTb4b4b4({ Te6edf3nameTb4b4b4: Ta5d6ff"messages" }Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
}
Tff7b72if Tb4b4b4(Tff7b72/Tff7b72^Te6edf3meshchatxTb4b4b4:\Tff7b72/\Tff7b72/Te6edf3app\Tff7b72/Tff7b72call\Tff7b72/Tff7b72?Tff7b72/Te6edf3iTb4b4b4.Te6edf3testTb4b4b4(Te6edf3normalizedUrlTb4b4b4)Tb4b4b4) {
Te6edf3thisTb4b4b4.$Te6edf3routerTb4b4b4.Te6edf3pushTb4b4b4({ Te6edf3nameTb4b4b4: Ta5d6ff"call"Tb4b4b4, Te6edf3queryTb4b4b4: { Te6edf3tabTb4b4b4: Ta5d6ff"phone" } }Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
}
Tff7b72try {
Te6edf3const Te6edf3u Tff7b72= Tff7b72new Te6edf3URLTb4b4b4(Te6edf3normalizedUrlTb4b4b4)Tb4b4b4;
Te6edf3const Te6edf3proto Tff7b72= Te6edf3uTb4b4b4.Te6edf3protocolTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3const Tff7b72host Tff7b72= Te6edf3uTb4b4b4.Te6edf3hostnameTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tb4b4b4(Te6edf3proto Tff7b72=Tff7b72=Tff7b72= Ta5d6ff"meshchatx:" Tff7b72|Tff7b72| Te6edf3proto Tff7b72=Tff7b72=Tff7b72= Ta5d6ff"meshchat:"Tb4b4b4) Tff7b72&Tff7b72& Tff7b72host Tff7b72=Tff7b72=Tff7b72= Ta5d6ff"docs"Tb4b4b4) {
Te6edf3let Te6edf3rel Tff7b72= Te6edf3uTb4b4b4.Te6edf3searchParamsTb4b4b4.Tff7b72getTb4b4b4(Ta5d6ff"reticulum"Tb4b4b4) Tff7b72?Tff7b72? Te6edf3uTb4b4b4.Te6edf3searchParamsTb4b4b4.Tff7b72getTb4b4b4(Ta5d6ff"path"Tb4b4b4) Tff7b72?Tff7b72? Ta5d6ff""Tb4b4b4;
Te6edf3rel Tff7b72= Te6edf3StringTb4b4b4(Te6edf3relTb4b4b4)Tb4b4b4.Tff7b72trimTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(!Te6edf3rel Tff7b72&Tff7b72& Te6edf3uTb4b4b4.Te6edf3pathname Tff7b72&Tff7b72& Te6edf3uTb4b4b4.Te6edf3pathname Tff7b72!=Tff7b72= Ta5d6ff"/"Tb4b4b4) {
Tff7b72try {
Te6edf3rel Tff7b72= Te6edf3decodeURIComponentTb4b4b4(Te6edf3uTb4b4b4.Te6edf3pathnameTb4b4b4.Td2a8ffreplaceTb4b4b4(Tff7b72/Tff7b72^\Tff7b72/Tff7b72+Tff7b72/Tb4b4b4, Ta5d6ff""Tb4b4b4)Tb4b4b4)Tb4b4b4;
} Tff7b72catch {
Te6edf3rel Tff7b72= Te6edf3uTb4b4b4.Te6edf3pathnameTb4b4b4.Td2a8ffreplaceTb4b4b4(Tff7b72/Tff7b72^\Tff7b72/Tff7b72+Tff7b72/Tb4b4b4, Ta5d6ff""Tb4b4b4)Tb4b4b4;
}
}
Tff7b72if Tb4b4b4(Te6edf3relTb4b4b4) {
Te6edf3thisTb4b4b4.$Te6edf3routerTb4b4b4.Te6edf3pushTb4b4b4({
Te6edf3nameTb4b4b4: Ta5d6ff"documentation"Tb4b4b4,
Te6edf3queryTb4b4b4: { Te6edf3reticulumTb4b4b4: Te6edf3encodeURIComponentTb4b4b4(Te6edf3relTb4b4b4) }Tb4b4b4,
}Tb4b4b4)Tb4b4b4;
} Tff7b72else {
Te6edf3thisTb4b4b4.$Te6edf3routerTb4b4b4.Te6edf3pushTb4b4b4({ Te6edf3nameTb4b4b4: Ta5d6ff"documentation" }Tb4b4b4)Tb4b4b4;
}
Tff7b72returnTb4b4b4;
}
} Tff7b72catch {
T8b949e/*T8b949e not a valid URL; continue T8b949e*/
}
Tff7b72if Tb4b4b4(Tff7b72/Tff7b72^Tb4b4b4(Te6edf3meshchatxTff7b72|Te6edf3meshchatTb4b4b4):\Tff7b72/\Tff7b72/Tff7b72map\Te6edf3bTff7b72/Te6edf3iTb4b4b4.Te6edf3testTb4b4b4(Te6edf3normalizedUrlTb4b4b4)Tb4b4b4) {
Te6edf3WebSocketConnectionTb4b4b4.Te6edf3sendTb4b4b4(
Te6edf3JSONTb4b4b4.Te6edf3stringifyTb4b4b4({
Te6edf3typeTb4b4b4: Ta5d6ff"lxm.ingest_uri"Tb4b4b4,
Te6edf3uriTb4b4b4: Te6edf3normalizedUrlTb4b4b4,
}Tb4b4b4)
Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
}
Tff7b72if Tb4b4b4(Tff7b72/Tff7b72^Tb4b4b4(Te6edf3meshchatxTff7b72|Te6edf3meshchatTb4b4b4):\Tff7b72/\Tff7b72/Te6edf3relay\Te6edf3bTff7b72/Te6edf3iTb4b4b4.Te6edf3testTb4b4b4(Te6edf3normalizedUrlTb4b4b4)Tb4b4b4) {
Te6edf3thisTb4b4b4.Te6edf3openRelayShareLinkTb4b4b4(Te6edf3normalizedUrlTb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
}
Tff7b72if Tb4b4b4(Tff7b72/Tff7b72^Tb4b4b4(Te6edf3meshchatxTff7b72|Te6edf3meshchatTb4b4b4):\Tff7b72/\Tff7b72/Tff7b72/Te6edf3iTb4b4b4.Te6edf3testTb4b4b4(Te6edf3normalizedUrlTb4b4b4)Tb4b4b4) {
Tff7b72try {
Te6edf3const Te6edf3u Tff7b72= Tff7b72new Te6edf3URLTb4b4b4(Te6edf3normalizedUrlTb4b4b4)Tb4b4b4;
Te6edf3const Tff7b72host Tff7b72= Tb4b4b4(Te6edf3uTb4b4b4.Te6edf3hostname Tff7b72|Tff7b72| Ta5d6ff""Tb4b4b4)Tb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72host Tff7b72&Tff7b72& !Tff7b72[Te6edf3"map", "docs", "relay", "app"Tff7b72]Tb4b4b4.Te6edf3includesTb4b4b4(Tff7b72hostTb4b4b4)Tb4b4b4) {
Te6edf3ToastUtilsTb4b4b4.Te6edf3errorTb4b4b4(Te6edf3thisTb4b4b4.$Te6edf3tTb4b4b4(Ta5d6ff"messages.unknown_meshchatx_link"Tb4b4b4, { Tff7b72host }Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
}
} Tff7b72catch {
Te6edf3ToastUtilsTb4b4b4.Te6edf3errorTb4b4b4(Te6edf3thisTb4b4b4.$Te6edf3tTb4b4b4(Ta5d6ff"messages.unknown_meshchatx_link_generic"Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
}
}
Tff7b72if Tb4b4b4(Tff7b72/Tff7b72^Te6edf3lxmTb4b4b4(Te6edf3aTff7b72|Te6edf3fTb4b4b4)Tff7b72?:\Tff7b72/\Tff7b72/Tff7b72/Te6edf3iTb4b4b4.Te6edf3testTb4b4b4(Te6edf3normalizedUrlTb4b4b4)Tb4b4b4) {
Te6edf3WebSocketConnectionTb4b4b4.Te6edf3sendTb4b4b4(
Te6edf3JSONTb4b4b4.Te6edf3stringifyTb4b4b4({
Te6edf3typeTb4b4b4: Ta5d6ff"lxm.ingest_uri"Tb4b4b4,
Te6edf3uriTb4b4b4: Te6edf3normalizedUrlTb4b4b4,
}Tb4b4b4)
Tb4b4b4)Tb4b4b4;
}

Tff7b72/Tff7b72/ Te6edf3lxmaTb4b4b4:Tff7b72/Tff7b72/Tff7b72<Te6edf3hashTff7b72>:Tff7b72<Te6edf3pubkeyTff7b72> Tff7b72or Te6edf3lxmfTb4b4b4:Tff7b72/Tff7b72/Tff7b72<Te6edf3hashTff7b72> Tff7b72or Te6edf3rnsTb4b4b4:Tff7b72/Tff7b72/Tff7b72<Te6edf3hashTff7b72>
Te6edf3const Te6edf3cleanUrl Tff7b72= Te6edf3normalizedUrl
Tb4b4b4.Td2a8ffreplaceTb4b4b4(Tff7b72/Tff7b72^Te6edf3lxmaTb4b4b4:\Tff7b72/\Tff7b72/Tff7b72/Te6edf3iTb4b4b4, Ta5d6ff""Tb4b4b4)
Tb4b4b4.Td2a8ffreplaceTb4b4b4(Tff7b72/Tff7b72^Te6edf3lxmfTb4b4b4:\Tff7b72/\Tff7b72/Tff7b72/Te6edf3iTb4b4b4, Ta5d6ff""Tb4b4b4)
Tb4b4b4.Td2a8ffreplaceTb4b4b4(Tff7b72/Tff7b72^Te6edf3rnsTb4b4b4:\Tff7b72/\Tff7b72/Tff7b72/Te6edf3iTb4b4b4, Ta5d6ff""Tb4b4b4)Tb4b4b4;
Te6edf3const Te6edf3hash Tff7b72= Te6edf3cleanUrlTb4b4b4.Te6edf3splitTb4b4b4(Ta5d6ff":"Tb4b4b4)Tff7b72[Te6edf30Tff7b72]Tb4b4b4.Te6edf3splitTb4b4b4(Ta5d6ff"/"Tb4b4b4)Tff7b72[Te6edf30Tff7b72]Tb4b4b4.Td2a8ffreplaceTb4b4b4(Ta5d6ff"/"Tb4b4b4, Ta5d6ff""Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3hash Tff7b72&Tff7b72& Te6edf3hashTb4b4b4.Te6edf3length Tff7b72=Tff7b72=Tff7b72= T79c0ff32Tb4b4b4) {
Te6edf3thisTb4b4b4.$Te6edf3routerTb4b4b4.Te6edf3pushTb4b4b4({
Te6edf3nameTb4b4b4: Ta5d6ff"messages"Tb4b4b4,
Te6edf3paramsTb4b4b4: { Te6edf3destinationHashTb4b4b4: Te6edf3hash }Tb4b4b4,
}Tb4b4b4)Tb4b4b4;
}
} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) {
Te6edf3consoleTb4b4b4.Te6edf3errorTb4b4b4(Ta5d6ff"Failed to handle protocol link:"Tb4b4b4, Te6edf3eTb4b4b4)Tb4b4b4;
}
}Tb4b4b4,
Te6edf3async Te6edf3openRelayShareLinkTb4b4b4(Te6edf3uriTb4b4b4) {
Te6edf3const Te6edf3parsed Tff7b72= Te6edf3parseMeshchatRelayUriTb4b4b4(Te6edf3uriTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(!Te6edf3parsedTb4b4b4) {
Te6edf3ToastUtilsTb4b4b4.Te6edf3errorTb4b4b4(Te6edf3thisTb4b4b4.$Te6edf3tTb4b4b4(Ta5d6ff"messages.relay_link_invalid"Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
}
Tff7b72if Tb4b4b4(Te6edf3GlobalStateTb4b4b4.Te6edf3configTff7b72?Tb4b4b4.Te6edf3rrc_enabled Tff7b72=Tff7b72=Tff7b72= Tff7b72falseTb4b4b4) {
Te6edf3ToastUtilsTb4b4b4.Te6edf3warningTb4b4b4(Te6edf3thisTb4b4b4.$Te6edf3tTb4b4b4(Ta5d6ff"messages.relay_link_disabled"Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
}
Tff7b72try {
Te6edf3const Tff7b72result Tff7b72= Te6edf3await Te6edf3applyRelayShareLinkTb4b4b4(Te6edf3parsedTb4b4b4)Tb4b4b4;
Te6edf3await Te6edf3thisTb4b4b4.$Te6edf3routerTb4b4b4.Te6edf3pushTb4b4b4({
Te6edf3nameTb4b4b4: Ta5d6ff"relay-chat"Tb4b4b4,
Te6edf3queryTb4b4b4: {
Te6edf3hubTb4b4b4: Tff7b72resultTb4b4b4.Te6edf3hub_hashTb4b4b4,
Tb4b4b4.Tb4b4b4.Tb4b4b4.Tb4b4b4(Tff7b72resultTb4b4b4.Te6edf3room Tff7b72? { Te6edf3roomTb4b4b4: Tff7b72resultTb4b4b4.Te6edf3room } : {}Tb4b4b4)Tb4b4b4,
}Tb4b4b4,
}Tb4b4b4)Tb4b4b4;
Te6edf3ToastUtilsTb4b4b4.Te6edf3successTb4b4b4(Te6edf3thisTb4b4b4.$Te6edf3tTb4b4b4(Ta5d6ff"messages.relay_link_opened"Tb4b4b4)Tb4b4b4)Tb4b4b4;
} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) {
Te6edf3ToastUtilsTb4b4b4.Te6edf3errorTb4b4b4(Te6edf3eTb4b4b4.Te6edf3responseTff7b72?Tb4b4b4.Tff7b72dataTff7b72?Tb4b4b4.Te6edf3message Tff7b72|Tff7b72| Te6edf3thisTb4b4b4.$Te6edf3tTb4b4b4(Ta5d6ff"messages.relay_link_failed"Tb4b4b4)Tb4b4b4)Tb4b4b4;
}
}Tb4b4b4,
Te6edf3handleKeyboardShortcutTb4b4b4(Tff7b72actionTb4b4b4) {
Te6edf3switch Tb4b4b4(Tff7b72actionTb4b4b4) {
Tff7b72case Ta5d6ff"nav_messages":
Te6edf3thisTb4b4b4.$Te6edf3routerTb4b4b4.Te6edf3pushTb4b4b4({ Te6edf3nameTb4b4b4: Ta5d6ff"messages" }Tb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tff7b72case Ta5d6ff"nav_nomad":
Te6edf3thisTb4b4b4.$Te6edf3routerTb4b4b4.Te6edf3pushTb4b4b4({ Te6edf3nameTb4b4b4: Ta5d6ff"nomadnetwork" }Tb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tff7b72case Ta5d6ff"nav_map":
Te6edf3thisTb4b4b4.$Te6edf3routerTb4b4b4.Te6edf3pushTb4b4b4({ Te6edf3nameTb4b4b4: Ta5d6ff"map" }Tb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tff7b72case Ta5d6ff"nav_paper":
Te6edf3thisTb4b4b4.$Te6edf3routerTb4b4b4.Te6edf3pushTb4b4b4({ Te6edf3nameTb4b4b4: Ta5d6ff"paper-message" }Tb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tff7b72case Ta5d6ff"nav_archives":
Te6edf3thisTb4b4b4.$Te6edf3routerTb4b4b4.Te6edf3pushTb4b4b4({ Te6edf3nameTb4b4b4: Ta5d6ff"archives" }Tb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tff7b72case Ta5d6ff"nav_calls":
Te6edf3thisTb4b4b4.$Te6edf3routerTb4b4b4.Te6edf3pushTb4b4b4({ Te6edf3nameTb4b4b4: Ta5d6ff"call" }Tb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tff7b72case Ta5d6ff"nav_settings":
Te6edf3thisTb4b4b4.$Te6edf3routerTb4b4b4.Te6edf3pushTb4b4b4({ Te6edf3nameTb4b4b4: Ta5d6ff"settings" }Tb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tff7b72case Ta5d6ff"compose_message":
Te6edf3thisTb4b4b4.Te6edf3composeNewMessageTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tff7b72case Ta5d6ff"sync_messages":
Te6edf3thisTb4b4b4.Te6edf3syncPropagationNodeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72breakTb4b4b4;
Tff7b72case Ta5d6ff"command_palette":
Tff7b72/Tff7b72/ Te6edf3Command Te6edf3palette Te6edf3handles Te6edf3its Te6edf3own Te6edf3shortcut Te6edf3but Te6edf3we Te6edf3emit Te6edf3it Te6edf3just Tff7b72in Tff7b72case
Tff7b72breakTb4b4b4;
Tff7b72case Ta5d6ff"toggle_sidebar":
Te6edf3thisTb4b4b4.Te6edf3isSidebarCollapsed Tff7b72= !Te6edf3thisTb4b4b4.Te6edf3isSidebarCollapsedTb4b4b4;
Tff7b72breakTb4b4b4;
}
}Tb4b4b4,
}Tb4b4b4,
}Tb4b4b4;
Tff7b72<Tff7b72/Te6edf3scriptTff7b72>

Tff7b72<Te6edf3styleTff7b72>
Te6edf3@reference Ta5d6ff"../style.css"Tb4b4b4;
Tb4b4b4.Te6edf3banishedTff7b72-Tff7b72overlay {
Te6edf3@apply Tff7b72absolute Te6edf3insetTff7b72-T79c0ff0 Te6edf3zTff7b72-T79c0ff100 Te6edf3flex Te6edf3itemsTff7b72-Te6edf3center Te6edf3justifyTff7b72-Te6edf3center Te6edf3overflowTff7b72-Te6edf3hidden Te6edf3pointerTff7b72-Te6edf3eventsTff7b72-Tff7b72none Te6edf3roundedTff7b72-Tff7b72[Te6edf3inheritTff7b72]Tb4b4b4;
Te6edf3backgroundTb4b4b4: Te6edf3rgbaTb4b4b4(T79c0ff220Tb4b4b4, T79c0ff38Tb4b4b4, T79c0ff38Tb4b4b4, T79c0ff0.12Tb4b4b4)Tb4b4b4;
Te6edf3backdropTff7b72-Tff7b72filter: Te6edf3blurTb4b4b4(T79c0ff3Te6edf3pxTb4b4b4) Te6edf3saturateTb4b4b4(T79c0ff180Tff7b72%Tb4b4b4)Tb4b4b4;
}

Tb4b4b4.Te6edf3banishedTff7b72-T56d364text {
Te6edf3@apply Te6edf3fontTff7b72-Te6edf3black Te6edf3trackingTff7b72-Tff7b72[Te6edf30.3emTff7b72] Te6edf3uppercase Te6edf3pointerTff7b72-Te6edf3eventsTff7b72-Tff7b72none Te6edf3opacityTff7b72-T79c0ff40Tb4b4b4;
Te6edf3fontTff7b72-Tff7b72size: Te6edf3clampTb4b4b4(T79c0ff1.5Te6edf3remTb4b4b4, T79c0ff8Te6edf3vwTb4b4b4, T79c0ff6Te6edf3remTb4b4b4)Tb4b4b4;
Te6edf3colorTb4b4b4: Te6edf3#dc2626Tb4b4b4;
Te6edf3transformTb4b4b4: Te6edf3rotateTb4b4b4(Tff7b72-T79c0ff12Te6edf3degTb4b4b4)Tb4b4b4;
T56d364textTff7b72-Te6edf3shadowTb4b4b4: T79c0ff0 T79c0ff0 T79c0ff15Te6edf3px Te6edf3rgbaTb4b4b4(T79c0ff220Tb4b4b4, T79c0ff38Tb4b4b4, T79c0ff38Tb4b4b4, T79c0ff0.4Tb4b4b4)Tb4b4b4;
Te6edf3borderTb4b4b4: T79c0ff0.2Te6edf3em Te6edf3solid Te6edf3#dc2626Tb4b4b4;
Te6edf3paddingTb4b4b4: T79c0ff0.15Te6edf3em T79c0ff0.4Te6edf3emTb4b4b4;
Te6edf3borderTff7b72-Te6edf3radiusTb4b4b4: T79c0ff0.15Te6edf3emTb4b4b4;
Te6edf3backgroundTb4b4b4: Te6edf3rgbaTb4b4b4(T79c0ff255Tb4b4b4, T79c0ff255Tb4b4b4, T79c0ff255Tb4b4b4, T79c0ff0.05Tb4b4b4)Tb4b4b4;
}

Tb4b4b4.Te6edf3fadeTff7b72-Te6edf3blurTff7b72-Te6edf3enterTff7b72-Te6edf3activeTb4b4b4,
Tb4b4b4.Te6edf3fadeTff7b72-Te6edf3blurTff7b72-Te6edf3leaveTff7b72-Te6edf3active {
Te6edf3transitionTb4b4b4: Tff7b72all T79c0ff0.5Te6edf3s Te6edf3easeTb4b4b4;
}

Tb4b4b4.Te6edf3fadeTff7b72-Te6edf3blurTff7b72-Te6edf3enterTff7b72-Tff7b72fromTb4b4b4,
Tb4b4b4.Te6edf3fadeTff7b72-Te6edf3blurTff7b72-Te6edf3leaveTff7b72-Tff7b72to {
Te6edf3opacityTb4b4b4: T79c0ff0Tb4b4b4;
Te6edf3backdropTff7b72-Tff7b72filter: Te6edf3blurTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4;
}

Te6edf3@keyframes Tff7b72identityTff7b72-Te6edf3switchTff7b72-Te6edf3indeterminate {
T79c0ff0Tff7b72% {
Te6edf3transformTb4b4b4: Te6edf3translateXTb4b4b4(Tff7b72-T79c0ff100Tff7b72%Tb4b4b4)Tb4b4b4;
}
T79c0ff100Tff7b72% {
Te6edf3transformTb4b4b4: Te6edf3translateXTb4b4b4(T79c0ff350Tff7b72%Tb4b4b4)Tb4b4b4;
}
}

Tb4b4b4.Tff7b72identityTff7b72-Te6edf3switchTff7b72-Te6edf3indeterminate {
Te6edf3animationTb4b4b4: Tff7b72identityTff7b72-Te6edf3switchTff7b72-Te6edf3indeterminate T79c0ff1.4Te6edf3s Te6edf3easeTff7b72-Tff7b72inTff7b72-Tff7b72out Te6edf3infiniteTb4b4b4;
}
Tff7b72<Tff7b72/Te6edf3styleTff7b72>

Served by rngit 1.5.2 - Generated in 0.1s